19

この動作が想定されているかどうかはわかりませんが、バインドがインターフェイス タイプに割り当てられている場合、カスタム モデル バインドは機能しないようです。誰かがこれを実験しましたか?

public interface ISomeModel {}
public class SomeModel : ISomeModel {}

public class MvcApplication : HttpApplication {
    protected void Application_Start(object sender, EventArgs e) {
        ModelBinders.Binders[typeof(ISomeModel)] = new MyCustomModelBinder();
    }
}

上記のコードでは、タイプ SomeModel のモデルにバインドすると、MyCustomModelBinder がヒットすることはありません。ただし、上記のコードを変更し、まったく同じフォームを置き換えtypeof(ISomeModel)て投稿すると、MyCustomModelBinder が期待どおりに呼び出されます。typeof(SomeModel)それは正しいと思いますか?


編集

最初にこの質問をした後、1 年以上この苦境に陥っていましたが、今ではうまくいく解決策があります。ありがとうマット・ハイディンガー!

http://www.matthidinger.com/archive/2011/08/16/An-inheritance-aware-ModelBinderProvider-in-MVC-3.aspx

4

3 に答える 3

11

私はこの問題を実験していて、ある種の解決策を思いついた。InterfaceModelBinderというクラスを作成しました。

public class InterfaceModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        ModelBindingContext context = new ModelBindingContext(bindingContext);
        var item = Activator.CreateInstance(
            Type.GetType(controllerContext.RequestContext.HttpContext.Request.Form["AssemblyQualifiedName"]));

        Func<object> modelAccessor = () => item;
        context.ModelMetadata = new ModelMetadata(new DataAnnotationsModelMetadataProvider(),
            bindingContext.ModelMetadata.ContainerType, modelAccessor, item.GetType(), bindingContext.ModelName);

        return base.BindModel(controllerContext, context);
    }
}

Application_Startに次のように登録しました:

ModelBinders.Binders.Add(typeof(IFormSubmission), new InterfaceModelBinder.Models.InterfaceModelBinder());

インターフェイスと具体的な実装は次のようになります。

public interface IFormSubmission
{
}

public class ContactForm : IFormSubmission
{
    public string Name
    {
        get;
        set;
    }

    public string Email
    {
        get;
        set;
    }

    public string Comments
    {
        get;
        set;
    }
}

このアプローチ全体の唯一の欠点は(すでに収集しているかもしれませんが)、どこかからAssemblyQualifiedNameを取得する必要があることです。この例では、次のように、クライアント側で非表示フィールドとして格納されています。

<%=Html.HiddenFor(m => m.GetType().AssemblyQualifiedName) %>

タイプ名をクライアントに公開することの欠点が、このアプローチの利点を失う価値があるかどうかはわかりません。このようなアクションは、すべてのフォーム送信を処理できます。

[HttpPost]
public ActionResult Process(IFormSubmission form)
{
    if (ModelState.IsValid)
    {
        FormManager manager = new FormManager();
        manager.Process(form);
    }

    //do whatever you want
}

このアプローチについて何か考えはありますか?

于 2010-07-03T21:24:11.200 に答える
8

突然、MVC3 ソリューションが表示されます。

http://www.matthidinger.com/archive/2011/08/16/An-inheritance-aware-ModelBinderProvider-in-MVC-3.aspx

于 2011-10-19T18:57:08.333 に答える
5

直接関係があるかどうかはわかりませんが、モデルバインディングとインターフェースを使用するときに考慮する必要があることがあります...デフォルトのモデルバインダーで同様の問題に遭遇しましたが、方法によっては直接関係ない場合がありますあなたは何かをしている...

以下をご覧ください: ASP.net MVC v2 - モデル バインディングの問題のデバッグ - バグ? ASP.net MVC v2 - モデル バインドの問題のデバッグ - バグ?

于 2010-06-04T00:11:45.937 に答える