Asp.net MVC 中的自定义 DateTime 模型绑定器
我想为 DateTime
类型编写自己的模型绑定程序。首先,我想编写一个可以附加到我的模型属性的新属性,例如:
[DateTimeFormat("d.M.yyyy")]
public DateTime Birth { get; set,}
这是简单的部分。但活页夹部分有点困难。我想为 DateTime
类型添加一个新的模型绑定器。我可以
- 实现
IModelBinder
接口并编写自己的BindModel()
方法 - ,继承自
DefaultModelBinder
并覆盖BindModel()
我的模型
有一个如上所示的属性(Birth
)。因此,当模型尝试将请求数据绑定到此属性时,我的模型绑定器的 BindModel(controllerContext, BindingContext) 会被调用。一切都好,但是。 如何从控制器/绑定上下文获取属性,以正确解析我的日期?如何获取属性 Birth
的 PropertyDeciptor
?
编辑
由于关注点分离,我的模型类是在一个不(也不应该)引用 System.Web.MVC 程序集的程序集中定义的。此处禁止设置自定义绑定(类似于 Scott Hanselman 的示例)属性。
I would like to write my own model binder for DateTime
type. First of all I'd like to write a new attribute that I can attach to my model property like:
[DateTimeFormat("d.M.yyyy")]
public DateTime Birth { get; set,}
This is the easy part. But the binder part is a bit more difficult. I would like to add a new model binder for type DateTime
. I can either
- implement
IModelBinder
interface and write my ownBindModel()
method - inherit from
DefaultModelBinder
and overrideBindModel()
method
My model has a property as seen above (Birth
). So when the model tries to bind request data to this property, my model binder's BindModel(controllerContext, bindingContext)
gets invoked. Everything ok, but. How do I get property attributes from controller/bindingContext, to parse my date correctly? How can I get to the PropertyDesciptor
of property Birth
?
Edit
Because of separation of concerns my model class is defined in an assembly that doesn't (and shouldn't) reference System.Web.MVC assembly. Setting custom binding (similar to Scott Hanselman's example) attributes is a no-go here.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您可以使用 IModelBinder 更改默认模型绑定器以使用用户区域性
,并在 Global.Asax 中将以下内容添加到 Application_Start():
阅读更多信息 这个优秀的博客,描述了为什么 Mvc 框架团队向所有用户实施默认文化。
you can change the default model binder to use the user culture using IModelBinder
And in the Global.Asax add the following to Application_Start():
Read more at this excellent blog that describe why Mvc framework team implemented a default Culture to all users.
我自己也遇到了这个非常大的问题,经过几个小时的尝试和失败,我得到了一个像你问的那样的可行解决方案。
首先,由于仅在属性上拥有绑定器是不可能的,因此您必须实现完整的 ModelBinder。由于您不希望绑定所有单个属性,而只希望绑定您关心的属性,因此您可以从 DefaultModelBinder 继承,然后绑定单个属性:
在我的示例中,我正在使用固定区域性解析日期,但您想要做的是可能的。您应该创建一个 CustomAttribute (如 DateTimeFormatAttribute)并将其放在您的属性上:
现在,在 BindProperty 方法中,您可以使用 DateTimeFormatAttribute 查找属性,而不是查找 DateTime 属性,获取您在构造函数中指定的格式,然后解析DateTime.ParseExact 的日期
我希望这有帮助,我花了很长时间才找到这个解决方案。一旦我知道如何搜索它,实际上很容易获得这个解决方案:(
I had this very big problem myself and after hours of try and fail I got a working solution like you asked.
First of all since having a binder on just a property is not possibile yuo have to implement a full ModelBinder. Since you don't want the bind all the single property but only the one you care you can inherit from DefaultModelBinder and then bind the single property:
In my example I'm parsing date with a fiexed culture, but what you want to do is possible. You should create a CustomAttribute (like DateTimeFormatAttribute) and put it over you property:
Now in the BindProperty method, instead of looking for a DateTime property you can look for a property with you DateTimeFormatAttribute, grab the format you specified in the constructor and then parse the date with DateTime.ParseExact
I hope this helps, it took me very long to come with this solution. It was actually easy to have this solution once I knew how to search it :(
我认为您不应该将特定于区域设置的属性放在模型上。
此问题的另外两个可能的解决方案是:
要回答您的实际问题,获取自定义属性(对于 MVC 2)的方法是 编写 AssociatedMetadataProvider.
I don't think you should put locale-specific attributes on a model.
Two other possible solutions to this problem are:
To answer your actual question, the way to get custom attributes (for MVC 2) is to write an AssociatedMetadataProvider.
对于 ASP.NET Core,您可以使用以下自定义模型绑定器。
下面给出了一个示例模型。
日期时间值的自定义绑定器。它需要格式
dd/MM/yyyy
。For ASP.NET Core, you can use the following custom model binder.
A sample model is given below.
The custom binder for DateTime value. It expects the format
dd/MM/yyyy
.您可以像这样实现自定义 DateTime Binder,但您必须注意实际客户端请求中假定的区域性和值。您是否可以在 en-US 中获得像 mm/dd/yyyy 这样的日期,并希望将其转换为系统文化 en-GB(类似于 dd/mm/yyyy)或固定文化(就像我们一样),然后您必须先解析它并使用静态外观 Convert 来更改它的行为。
不管怎样,无状态应用程序中依赖于文化的 DateTime 解析可能会很残酷……特别是当您在 javascript 客户端和向后使用 JSON 时。
You could implement a custom DateTime Binder like so, but you have to take care about the assumed culture and value from the actual client request. May you get an Date like mm/dd/yyyy in en-US and want it to convert in the systems culture en-GB (which it would be like dd/mm/yyyy) or an invariant culture, like we do, then you have to parse it before and using the static facade Convert to change it in its behaviour.
Anyway, culture dependend DateTime parsing in a stateless Application can by a cruelty...Especially when you work with JSON on javascript clientside and backwards.