属性的自定义模型活页夹
我有以下控制器操作:
[HttpPost]
public ViewResult DoSomething(MyModel model)
{
// do something
return View();
}
其中 MyModel
看起来像这样:
public class MyModel
{
public string PropertyA {get; set;}
public IList<int> PropertyB {get; set;}
}
所以 DefaultModelBinder 应该毫无问题地绑定它。唯一的事情是我想使用特殊/自定义绑定器来绑定PropertyB,并且我还想重用这个绑定器。所以我认为解决方案是在 PropertyB 之前放置一个 ModelBinder 属性,这当然不起作用(属性上不允许使用 ModelBinder 属性)。我看到两种解决方案:
在每个属性而不是整个模型上使用操作参数(我不喜欢这样,因为模型有很多属性),如下所示:
public ViewResult DoSomething(string propertyA, [ModelBinder(typeof(MyModelBinder))] propertyB)
要创建一个新类型,可以这样说
MyCustomType: List
并为此类型注册模型绑定器(这是一个选项)也许要为 MyModel 创建绑定器,覆盖
BindProperty
并且如果属性是"PropertyB"
则绑定财产与我的定制活页夹。这可能吗?
还有其他解决办法吗?
I have the following controller action:
[HttpPost]
public ViewResult DoSomething(MyModel model)
{
// do something
return View();
}
Where MyModel
looks like this:
public class MyModel
{
public string PropertyA {get; set;}
public IList<int> PropertyB {get; set;}
}
So DefaultModelBinder should bind this without a problem. The only thing is that I want to use special/custom binder for binding PropertyB
and I also want to reuse this binder. So I thought that solution would be to put a ModelBinder attribute before the PropertyB which of course doesn't work (ModelBinder attribute is not allowed on a properties). I see two solutions:
To use action parameters on every single property instead of the whole model (which I wouldn't prefer as the model has a lot of properties) like this:
public ViewResult DoSomething(string propertyA, [ModelBinder(typeof(MyModelBinder))] propertyB)
To create a new type lets say
MyCustomType: List<int>
and register model binder for this type (this is an option)Maybe to create a binder for MyModel, override
BindProperty
and if the property is"PropertyB"
bind the property with my custom binder. Is this possible?
Is there any other solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
属性级绑定的自定义属性,而不是检查“is PropertyB”,例如
您可以看到 BindProperty override 的示例 此处。
That's a good solution, though instead of checking "is PropertyB" you better check for your own custom attributes that define property-level binders, like
You can see an example of BindProperty override here.
我实际上喜欢你的第三个解决方案,只是,我会将其放入继承自
DefaultModelBinder
的自定义绑定器中,并将其配置为 MVC 的默认模型绑定器,从而使其成为所有 ModelBinder 的通用解决方案应用。然后,您可以使用参数中提供的类型,使这个新的
DefaultModelBinder
自动绑定用PropertyBinder
属性修饰的任何属性。我从这篇优秀的文章中得到了这个想法: http://aboutcode.net/2011/03/12 /mvc-property-binder.html。
我还将向您展示我对解决方案的看法:
我的
DefaultModelBinder
:我的
IPropertyBinder
界面:我的
PropertyBinderAttribute
:属性绑定器示例:
使用上述属性绑定器的示例:
I actually like your third solution, only, I would make it a generic solution for all ModelBinders, by putting it in a custom binder that inherits from
DefaultModelBinder
and is configured to be the default model binder for your MVC application.Then you would make this new
DefaultModelBinder
automatically bind any property that is decorated with aPropertyBinder
attribute, using the type supplied in the parameter.I got the idea from this excellent article: http://aboutcode.net/2011/03/12/mvc-property-binder.html.
I'll also show you my take on the solution:
My
DefaultModelBinder
:My
IPropertyBinder
interface:My
PropertyBinderAttribute
:An example of a property binder:
Example of the above property binder being used:
@jonathanconway 的答案很好,但我想添加一个小细节。
为了让
DefaultBinder
的验证机制有机会工作,最好重写GetPropertyValue
方法而不是BindProperty
。@jonathanconway's answer is great, but I would like to add a minor detail.
It's probably better to override the
GetPropertyValue
method instead ofBindProperty
in order to give the validation mechanism of theDefaultBinder
a chance to work.这个问题提出已经有6年了,我宁愿借这个空间来总结一下更新,而不是提供一个全新的解决方案。在撰写本文时,MVC 5 已经存在很长一段时间了,而 ASP.NET Core 刚刚问世。
我遵循 Vijaya Anand 撰写的文章中检查的方法(顺便说一句,感谢 Vijaya): ">http://www.prideparrot.com/blog/archive/2012/6/customizing_property_binding_through_attributes。还有一点值得注意的是,数据绑定逻辑放在自定义属性类中,即Vijaya Anand示例中的StringArrayPropertyBindAttribute类的BindProperty方法。
然而,在我读过的关于这个主题的所有其他文章(包括@jonathanconway的解决方案)中,自定义属性类只是引导框架找出要应用的正确自定义模型绑定器的垫脚石;绑定逻辑放置在自定义模型绑定器中,通常是 IModelBinder 对象。
第一种方法对我来说更简单。第一种方法可能存在一些我还不知道的缺点,因为我目前对 MVC 框架还很陌生。
另外,我发现Vijaya Anand示例中的ExtendModelBinder类在MVC 5中是不必要的。看来MVC 5自带的DefaultModelBinder类足够聪明,可以与自定义模型绑定属性配合。
It has been 6 years since this question was asked, I would rather take this space to summarize the update, instead of providing a brand new solution. At the time of writing, MVC 5 has been around for quite a while, and ASP.NET Core has just come out.
I followed the approach examined in the post written by Vijaya Anand (btw, thanks to Vijaya): http://www.prideparrot.com/blog/archive/2012/6/customizing_property_binding_through_attributes. And one thing worth noting is that, the data binding logic is placed in the custom attribute class, which is the BindProperty method of the StringArrayPropertyBindAttribute class in Vijaya Anand's example.
However, in all the other articles on this topic that I have read (including @jonathanconway's solution), custom attribute class is only a step stone that leads the framework to find out the correct custom model binder to apply; and the binding logic is placed in that custom model binder, which is usually an IModelBinder object.
The 1st approach is simpler to me. There may be some shortcomings of the 1st approach, that I haven't known yet, though, coz I am pretty new to MVC framework at the moment.
In addition, I found that the ExtendedModelBinder class in Vijaya Anand's example is unnecessary in MVC 5. It seems that the DefaultModelBinder class which comes with MVC 5 is smart enough to cooperate with custom model binding attributes.