ASP.NET MVC - 接口类型上的自定义模型绑定器

Nat*_*lor 19 asp.net-mvc interface modelbinders

我不确定这种行为是否是预期的,但是当绑定分配给接口类型时,似乎自定义模型绑定不起作用.有人试过这个吗?

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

使用上面的代码,当我绑定到SomeModel类型的模型时,MyCustomModelBinder永远不会被击中; 但是,如果我改变了上面的代码,并替代typeof(ISomeModel)typeof(SomeModel)预期并张贴完全相同的形式MyCustomModelBinder被调用.那似乎对吗?


编辑

在我最初提出这个问题一年后,我发现自己已经陷入了这种困境,现在我有一个有效的解决方案.谢谢Matt Hidinger!

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

Nat*_*son 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我在我的Application_Start中注册了如下:

ModelBinders.Binders.Add(typeof(IFormSubmission), new InterfaceModelBinder.Models.InterfaceModelBinder());
Run Code Online (Sandbox Code Playgroud)

接口和具体实现如下所示:

public interface IFormSubmission
{
}

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

    public string Email
    {
        get;
        set;
    }

    public string Comments
    {
        get;
        set;
    }
}
Run Code Online (Sandbox Code Playgroud)

整个方法的唯一缺点(正如您可能已经收集的那样)是我需要从某个地方获取AssemblyQualifiedName,并且在此示例中,它被存储为客户端的隐藏字段,如下所示:

<%=Html.HiddenFor(m => m.GetType().AssemblyQualifiedName) %>
Run Code Online (Sandbox Code Playgroud)

我不确定将类型名称暴露给客户端的缺点是值得失去这种方法的好处.像这样的Action可以处理我提交的所有表单:

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

    //do whatever you want
}
Run Code Online (Sandbox Code Playgroud)

有关这种方法的任何想法?

  • 也许解决这个问题的方法是对客户端上的类型名称进行散列或加密,然后在模型绑定器中对其进行处理. (2认同)

ant*_*nyv 5

我不确定它是否直接相关,但是在使用模型绑定和接口时需要考虑的事情......我遇到了与默认模型绑定器类似的问题,但它可能不是直接相关的取决于如何你在做什么......

看看以下内容: ASP.net MVC v2 - 调试模型绑定问题 - BUG? ASP.net MVC v2 - 调试模型绑定问题 - BUG?