适用于多种类型的MVC自定义ModelBinding

时间:2016-02-15 19:26:56

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

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

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

Random rnd = new Random();

//inside nested for loop
while (value has already been picked){
    // gives a random value btwen 0 and (n*n)-1
    value = rnd.nextInt((n*n));
}

// value has not been used
puzzle [i][j]= value;

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

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

其中ModelBinders.Binders.Add(typeof(ViewModelBase), new JsonPropertyBinder()); ViewModelOneViewModelTwo继承。我试过这个,但我没有运气。问题在于,需要自定义绑定的属性不在ViewModel基础中。我们真正想要的是以通用方式实现我的模型绑定器的优雅解决方案。

我的viewmodels中的属性也有自定义绑定的自定义属性ViewModelBase,然后我在绑定器中检查这个属性:

[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); } } 属性添加到我的viewmodel中,但没有成功。虽然,我不确定我喜欢这种方法,因为我想将活页夹的注册保留在一个地方,而不是分散

- 编辑 - 我想我可以创建一个继承自[ModelBinder]的中间类(例如ViewModelIntermediate),只包含我要自定义绑定的属性,然后有ViewModelBase和{{1从ViewModelOne继承,以便我可以使用派生的ViewModel注册一次绑定,例如

ViewModelTwo

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

现在我认为我可能需要声明一个新的默认绑定器,它继承自DefaultModelBinder并且在那里有一些逻辑来检查某些(或自定义)属性并相应地处理它们。像this

这样的东西

1 个答案:

答案 0 :(得分:4)

我认为您可能正在寻找的是一个自定义模型绑定提供程序..基本上是一个超级抽象,它决定了模型类型所使用的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());

P.S。 nit:为了清楚起见,我会将JsonPropertyBinder重命名为JsonPropertyModelBinder