1

我正在追踪 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) 应该选择正确的属性,这取决于模型的实际实例是 BaseModel 还是 RequiredModel。

这就是理论。

事实上,如果您使用“旧的”HTML 帮助器,例如@Html.TextBox(“MyLabel”),它会很好地工作。这些调用 ModelMetadata.FromStringExpression(field),如果具体模型实例是RequiredModel,它会正确地从RequiredModel 获取元数据。较新的辅助方法调用 ModelMetadata.FromLambdaExpression(expression),它不能正确地从正确的具体实例中获取元数据。

这是MVC中的错误吗?故意行为?是否有解决方法或更好的方法来解决此问题?

这当然是一个简单的例子,我们正在处理的实际代码有大约 20 个字段,其中包含一些复杂的业务规则和交互,这在两个页面上都是相同的,除了需要哪些字段。

4

1 回答 1

0

这就是理论。

不,这不是理论。至少不是我的。

我的理论是为每个视图使用单独的视图模型,因为您的视图的要求是不同的。所以你会有这个:

public class UpdateViewModel
{
    [Display(Name = "My Label")]
    public string MyLabel { get; set ;}
}

和:

public class CreateViewModel
{
    [Display(Name = "My Label")]
    [Required]
    public string MyLabel { get; set ;}
}

就个人而言,这就是我会做的。我会完全牺牲 DRY 来设计视图模型,因为我的视图要求经常变化,我想要完全控制。

显然,在实践中,我什至不费心使用声明性 DataAnnotations 属性进行验证。他们限制了我。我使用FluentValidation.NET,它以一种非常优雅的方式解决了像你这样的问题(通过简单地为同一个视图模型定义两个不同的验证器——以防你决定违反我的理论并在不同的视图中使用相同的视图模型)。

现在请随意对我的回答投反对票。我刚刚给了我的 2 美分。

于 2011-07-18T19:27:29.960 回答