【问题标题】:MVC custom ModelBinding for multiple types多种类型的 MVC 自定义 ModelBinding
【发布时间】:2016-02-15 19:26:55
【问题描述】:

我们有一个自定义模型绑定器,可以将 json 反序列化为对象列表,我想将该模型绑定器用于多个视图,每个视图都使用不同的视图模型。

我们要避免必须为每个视图模型注册模型绑定器,如下所示:

ModelBinders.Binders.Add(typeof(ViewModelOne), new JsonPropertyBinder());
ModelBinders.Binders.Add(typeof(ViewModelTwo), new JsonPropertyBinder());

我们想做的是让 ViewModel 从一个基类(他们这样做)派生并注册该基类:

ModelBinders.Binders.Add(typeof(ViewModelBase), new JsonPropertyBinder());

其中ViewModelOneViewModelTwo 继承形式ViewModelBase。我已经尝试过了,但我没有任何运气。那里的问题是需要自定义绑定的属性不在基本 ViewModel 中。我们真正想要的是一个优雅的解决方案,以通用方式实现我的模型绑定器。

我们的视图模型中的属性上还有一个自定义属性[JsonBindable] 要自定义绑定,然后我在活页夹中检查此属性:

public class JsonPropertyBinder : DefaultModelBinder
    {
        protected override object GetPropertyValue(ControllerContext controllerContext, System.Web.Mvc.ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, System.Web.Mvc.IModelBinder propertyBinder)
        {
            if (propertyDescriptor.Attributes.OfType<Attribute>().Any(x => (x is JsonBindableAttribute)))
            {
                var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue;
                return JsonConvert.DeserializeObject(value, propertyDescriptor.PropertyType);
            }

            return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
        }
    }

我尝试将[ModelBinder] 属性添加到我的视图模型,但没有成功。虽然,我不确定我是否喜欢这种方法,因为我想将活页夹的注册保留在一个地方,而不是分散开

-- 编辑-- 我想我可以创建一个从ViewModelBase继承的中间类(例如ViewModelIntermediate),只包含我想要自定义绑定的属性,然后让ViewModelOneViewModelTwo继承自ViewModelIntermediate所以我可以使用派生的 ViewModel 注册一次活页夹,例如

ModelBinders.Binders.Add(typeof(ViewModelIntermediate), new JsonPropertyBinder());

但这似乎是一个笨拙的解决方案。我希望能够声明一次自定义绑定器并将其与任何视图模型一起使用 - 而不必将我的类抽象为遗忘。

现在我在想我可能必须声明一个新的默认绑定器,它继承自 DefaultModelBinder 并在其中有一些逻辑来检查某些(或自定义)属性并相应地处理它们。类似this

【问题讨论】:

    标签: c# asp.net-mvc model-binding


    【解决方案1】:

    我认为您可能正在寻找的是自定义模型绑定提供程序。基本上是一个超级抽象,根据模型类型确定要使用的 ModelBinder。

    所以基本上,实现IModelBinderProvider 接口,并让GetBinder 方法根据您的标准返回您的模型绑定器。

    public class ViewModelBaseBinderProvider
        : IModelBinderProvider
    {
        public IModelBinder GetBinder(Type modelType)
        {
            // this or whatever condition you want to apply to determine
            // if your model binder needs to be used.
            if (typeof(ViewModelBase).IsAssignableFrom(modelType))
                return new JsonPropertyBinder();
    
            // this means, the view model did not match our criteria   
            // let it flow through the usual model binders.       
            return null;
        }
    }
    

    一旦你定义了自定义提供者,在你的应用程序开始注册如下:

    ModelBinderProviders.BinderProviders.Add(new ViewModelBaseBinderProvider());
    

    附言nit:为了清楚起见,我会将JsonPropertyBinder 重命名为JsonPropertyModelBinder

    【讨论】:

    • 感谢您的回答,但这并不是我想要的。如果我错了,请纠正我,但是使用您的解决方案,确定要使用哪个活页夹的所有逻辑都必须在此 GetBinder 方法中一起使用。
    • 不。这里唯一的逻辑是确定您的模型活页夹是否需要被拾取。如果条件与您的条件不匹配,我们只返回 null 并且 MVC 负责运行所有其他 BindingProvider(如果有),最后是默认的。请注意,我们只是将自定义 bindingprovider 添加到 MVC 的提供者列表中。我们没有替换任何东西
    • 好酷。谢谢!然后它听起来确实像我正在寻找的东西。我会尽快试用
    • @RajaNadar 只是想让你知道今天这对我有很大帮助。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2014-06-22
    • 2023-03-17
    • 2015-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-29
    相关资源
    最近更新 更多