代码之家  ›  专栏  ›  技术社区  ›  Nathan Taylor

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

  •  18
  • Nathan Taylor  · 技术社区  · 16 年前

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

    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

    3 回复  |  直到 15 年前
        1
  •  5
  •   Community Mohan Dere    9 年前

    我不确定它是否直接相关,但是的,在使用模型绑定和接口时需要考虑一些事情。。。我在使用默认模型绑定器时遇到了类似的问题,但这可能与您的操作方式没有直接关系。。。

    ASP.net MVC v2-调试模型绑定问题-错误? ASP.net MVC v2 - Debugging Model Binding Issues - BUG?

        2
  •  11
  •   Nathan Anderson    16 年前

    我在试验这个问题,我想出了一个解决办法。我做了一个叫做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);
        }
    }
    

    我在我的申请表中注册了它

    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
    }
    

    对这种方法有什么想法吗?