检索模型元数据的 HtmlHelper 方法中的行为不一致
我正在追踪 MVC3 中的意外行为,该行为与它获取模型元数据的方式有关。
我之前曾与我的一位开发人员讨论过,对于在系统的两个不同区域收集的一些数据使用相同的 EditorTemplate。除了 [Required] 属性之外,数据字段几乎相同。在一个页面中某些字段是必需的,而在另一页中则不是。理论上,这可以通过使用每个字段具有公共属性的基本模型并继承这些模型、覆盖属性并添加其他验证属性来实现。例如:
class BaseModel
{
[Display(Name=”My Label”)]
public virtual string MyLabel { get; set ;}
}
class RequiredModel : BaseModel
{
[Required]
public override string MyLabel { get; set ;}
}
然后视图可以强类型化为 BaseModel,并且在视图中调用 @Html.EditorFor(m=>m.MyLabel) 应该选取正确的属性,具体取决于模型的实际实例是否是基本模型或必需模型。
这就是理论。
事实上,如果您使用“旧的”HTML 帮助器,例如@Html.TextBox(“MyLabel”),它会很好地工作。这些调用 ModelMetadata.FromStringExpression(field),如果具体模型实例是RequiredModel,它会正确地从RequiredModel 获取元数据。较新的帮助程序方法调用 ModelMetadata.FromLambdaExpression(expression),它无法从正确的具体实例中正确获取元数据。
这是 MVC 中的错误吗?故意行为?有没有解决方法或更好的方法来解决这个问题?
这当然是一个简单的例子,我们正在处理的实际代码有大约 20 个字段,其中包含一些复杂的业务规则和交互,除了哪些字段是必需的之外,这在两个页面上都是相同的。
I’m tracing down an unexpected behavior in MVC3, having to do with how it gets model metadata.
I had previously talked to one of my developers about using the same EditorTemplate for some data which is collected in two different areas of the system. The data fields are almost identical, except for the [Required] attribute. In one page certain fields are required, in the other page they are not. Theoretically this can be accomplished by using a base model which has the common attributes on each field, and inheriting those models, overriding the properties and adding additional validation attributes. For example:
class BaseModel
{
[Display(Name=”My Label”)]
public virtual string MyLabel { get; set ;}
}
class RequiredModel : BaseModel
{
[Required]
public override string MyLabel { get; set ;}
}
Then the View can be strongly typed to BaseModel, and calls to @Html.EditorFor(m=>m.MyLabel) in the view should pick up the correct attributes, depending on whether the actual instance of the model is a BaseModel or RequiredModel.
That’s the theory.
And in fact, it works well if you use the “old” HTML helper, e.g. @Html.TextBox(“MyLabel”). Those call ModelMetadata.FromStringExpression(field), which correctly gets the metadata from RequiredModel if the concrete model instance is RequiredModel. The newer helper methods call ModelMetadata.FromLambdaExpression(expression), which does NOT correctly get the metadata from the correct concrete instance.
Is this a bug in MVC? Intentional behavior? Is there a workaround, or a better way to address this problem?
This is of course a trivial example, the actual code we're dealing with has about 20 fields with some complex business rules and interaction, which is the same on both pages EXCEPT for which fields are required.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不,这不是理论。至少不是我的。
我的理论是为每个视图使用单独的视图模型,因为视图的要求不同。所以你会得到这样的:
和:
就我个人而言,这就是我会做的。我会完全牺牲 DRY 来设计视图模型,因为我的视图的需求经常变化,而且我想要完全控制。
显然,在实践中,我什至不费心使用声明性 DataAnnotations 属性进行验证。他们限制了我。我使用 FluentValidation.NET 它以一种非常优雅的方式解决像你这样的问题(通过简单地为相同的视图模型 - 如果您决定违反我的理论并在不同的视图中使用相同的视图模型)。
现在请随意否决我的答案。我刚刚给了我的 2 美分。
No, that's not the theory. At least not mine.
My theory is to use separate view models for each views because the requirements of your views are different. So you would have this:
and:
Personally that's what I would do. I would totally sacrify DRY into designing view models because the requirements of my view change often and I want to have total control.
Obviously in practice I don't even bother with doing validation using declarative DataAnnotations attributes. They limit me. I use FluentValidation.NET which addresses problems like yours in a pretty elegant manner (by simply defining two different validators for the same view model - in case you decide to violate my theory and use the same view model in different views).
Now feel free to downvote my answer. I have just given my 2¢.