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

发布于 2024-09-04 07:32:16 字数 972 浏览 11 评论 0原文

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

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。这看起来对吗?


编辑

在我最初提出这个问题一年多后,我发现自己又陷入了这种困境,现在我有了一个有效的解决方案。谢谢马特·希丁格!

https://web.archive.org/web/20191202065649/http://matthidinger.com:80/archive/2011/08/16/An-inheritance-aware-ModelBinderProvider-in -MVC-3/

I'm not sure if this behavior is expected or not, but it seems that custom model binding doesn't work when the binding is assigned to an interface type. Has anyone experimented with this?

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();
    }
}

With the above code when I bind to a model of type SomeModel, MyCustomModelBinder is never hit; however, if I change the above code and substitute typeof(ISomeModel) for typeof(SomeModel) and post the exact same form MyCustomModelBinder is called as expected. Does that seem right?


Edit

I found myself back in this predicament over a year after I originally asked this question, and now I have a solution that works. Thank you Matt Hidinger!

https://web.archive.org/web/20191202065649/http://matthidinger.com:80/archive/2011/08/16/An-inheritance-aware-ModelBinderProvider-in-MVC-3/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

峩卟喜欢 2024-09-11 07:32: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);
    }
}

我在 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
}

对此方法有什么想法吗?

I was experimenting with this issue and I came up with a solution of sorts. I made a class called 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);
    }
}

Which I registered in my Application_Start as so:

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

The interface and a concrete implementation look like this:

public interface IFormSubmission
{
}

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

    public string Email
    {
        get;
        set;
    }

    public string Comments
    {
        get;
        set;
    }
}

The only downside to this whole approach (as you might have gathered already) is that I need to get the AssemblyQualifiedName from somewhere, and in this example it is being stored as a hidden field on the client side, like so:

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

I'm not certain though that the downsides of exposing the Type name to the client are worth losing the benefits of this approach. An Action like this can handle all my form submissions:

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

    //do whatever you want
}

Any thoughts on this approach?

人心善变 2024-09-11 07:32:16

我不确定它是否直接相关,但是是的,在使用模型绑定和接口时,您需要考虑一些事情...我在默认模型绑定程序中遇到了类似的问题,但它可能不直接相关,具体取决于如何你正在做的事情...

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

I'm not sure if its directly related but yes there are things that you need to think about when using model binding and interfaces... I ran into similar problems with the default model binder, but it may not be directly related depending on how you are doing things...

Have a look at the following:
ASP.net MVC v2 - Debugging Model Binding Issues - BUG?
ASP.net MVC v2 - Debugging Model Binding Issues - BUG?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文