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)typeof(SomeModel)发布完全相同的表单 MyCustomModelBinder 会按预期调用。这看起来对吗?


编辑

在我最初提出这个问题一年多之后,我发现自己又回到了这个困境中,现在我有了一个可行的解决方案。谢谢马特·希丁格!

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) %>

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

[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 - 调试模型绑定问题 - BUG? ASP.net MVC v2 - 调试模型绑定问题 - BUG?

于 2010-06-04T00:11:45.937 回答