ASP.NET MVC ModelBinding Inherited Classes

时间:2009-12-01 23:28:34

标签: asp.net-mvc inheritance modelbinders

我有一个关于ASP.NET MVC中的ModelBinding的问题(我正在使用MVC 2预览2)与继承相关。

说我有以下接口/类:

interface IBase
class Base : IBase
interface IChild
class Child: Base, IChild

我有一个自定义模型绑定器BaseModelBinder。

以下工作正常:

ModelBinders.Binders[typeof(Child)] = new BaseModelBinder();
ModelBinders.Binders[typeof(IChild)] = new BaseModelBinder();

以下不起作用(在绑定Child类型的on对象时):

ModelBinders.Binders[typeof(Base)] = new BaseModelBinder();
ModelBinders.Binders[typeof(IBase)] = new BaseModelBinder();

有没有办法让基类的模型绑定器适用于所有继承的类?我真的不想为每个可能的继承类手动输入内容。

此外,如果可能,是否有办法覆盖特定继承类的模型绑定器?说我得到了这个工作,但我需要一个特定的Child2的模型绑定器。

提前致谢。

2 个答案:

答案 0 :(得分:6)

我采用了一个简单的路由,我只是在启动时使用反射动态注册所有派生类。也许这不是一个干净的解决方案,但它在初始化代码中只有几行才能正常工作; - )

但如果你真的想搞砸模型粘合剂(你 > - 最终 - 但是有更好的方法可以花时间;-)你可以阅读thisthis

答案 1 :(得分:1)

好吧,我想有一种方法是对ModelBindersDictionary类进行子类化并覆盖GetBinders(Type typeType,bool fallbackToDefault)方法。

public class CustomModelBinderDictionary : ModelBinderDictionary
{
    public override IModelBinder GetBinder(Type modelType, bool fallbackToDefault)
    {
        IModelBinder binder = base.GetBinder(modelType, false);

        if (binder == null)
        {
            Type baseType = modelType.BaseType;
            while (binder == null && baseType != typeof(object))
            {
                binder = base.GetBinder(baseType, false);
                baseType = baseType.BaseType;
            }
        }

        return binder ?? DefaultBinder;
    }
}

基本上遍历类层次结构,直到找到模型绑定器或默认为DefaultModelBinder

下一步是让框架接受CustomModelBinderDictionary。据我所知,您需要对以下三个类进行子类化并覆盖Binders属性:DefaultModelBinderControllerActionInvokerController。您可能希望提供自己的静态CustomModelBinders类。

免责声明:这只是一个粗略的原型。我不确定它是否真的有效,它可能带来什么影响,或者它是否是一种合理的方法。您可能希望自己下载框架的code并进行试验。

<强>更新

我想另一种解决方案是定义您自己的CustomModelBindingAttribute

public class BindToBase : CustomModelBinderAttribute
{
    public override IModelBinder GetBinder()
    {
        return new BaseModelBinder();
    }
}

public class CustomController
{
   public ActionResult([BindToBase] Child child)
   {
       // Logic.
   }
}