C# - 使用MVVM中的DataAnnotations进行验证并在View中显示有意义的错误消息

时间:2012-09-19 07:06:30

标签: validation c#-4.0 mvvm data-annotations

假设我有一个这样的域模型:

public class MyDomainEntity
{
    public double SomeVar { get; set; }
}

我有一个视图,我想以百分比显示SomeVar。所以我的视图模型看起来像:

public class MyViewEntity
{
    public double SomeVarAsPercentage { get; set; }
}

我有一个映射类,它在视图模型和域模型之间进行映射,它简单地将变量除以并乘以100。

现在我想对域模型进行一些验证。在这种情况下,业务规则规定域模型中的SomeVar必须介于0.0和1.0之间。这可以通过System.ComponentModel.DataAnnotations.RangeAttribute轻松完成:

public class MyDomainEntity
{
    [Range(0.0, 1,0)]
    public double SomeVar { get; set; }
}

我可以使用

执行验证
MyDomainEntity r = new MyDomainEntity();

...
//mapping code from view-model to domain model
...

IList<ValidationResult> results = new List<ValidationResult>();
ValidationContext context = new ValidationContext(r, null, null);
Validator.TryValidateObject(r, context, results, true);
foreach (ValidationResult e in results)
{
    //I would like to display the error messages, if any, to the user
}

但是,由于验证是在域模型中完成的,因此错误消息如下所示:

"The field SomeVar must be between 0 and 1"

而上述错误消息需要转换为视图模型才能阅读:

"The field SomeVarAsPercentage must be between 0 and 100"

以便对用户有意义。

这里的问题是:

  1. DataAnnotations是否有能力执行此操作“错误消息转换”?
  2. 在这种情况下我不应该在域模型中进行验证吗?
  3. 也许DataAnnotations作为验证机制在这里不够或不合适?如果是这种情况,请提出其他一些框架
  4. 更新

    我更多地考虑了这个问题,似乎有几种方法

    方法1:在View-Model中验证

    将验证移至视图模型,如下所示:

    public class MyViewEntity
    {
        [Range(0.0, 100.0)]
        public double SomeVarAsPercentage { get; set; }
    }
    

    因此DataAnnotations可以生成所需的错误消息。

    然而,在视图模型中进行验证(与域模型中相同)更为谨慎。假设我的表单可以在两个视图之间切换:一个SomeVar以百分比形式显示,另一个SomeVar以“原样”显示,但仅显示两个小数位。然后我必须做:

    public class MyViewEntity1
    {
        [Range(0.0, 100.0)]
        public double SomeVarAsPercentage { get; set; }
    }
    
    
    public class MyViewEntity2
    {
        [Range(0.0, 1.0)]
        public double SomeVarToTwoDp { get; set; }
    }
    

    我必须将Range规则放在两个地方,但两者都是相同的规则。

    优点:简单
    缺点:有点WET

    方法2:在域模型中验证,使用稍微修改的验证方法

    扩展DataAnnotations验证框架,使其不仅返回错误属性名称,还返回它违反的规则和错误消息工厂。因此,View-Model实体和Domain Model实体之间的映射将使用错误消息工厂和规则(也需要映射)生成有意义的错误消息。

    优势:更多DRY,验证规则仅在域模型中出现一次
    缺点:更复杂

1 个答案:

答案 0 :(得分:1)

我想说你应该在两个地方进行验证 - ViewModel中的SomeVarAsPercentage,根据需要显示你的ViewModel验证错误信息,并丢弃无效输入(即不要将它们传递给模型)。

然后,在您的模型中,您可以验证SomeVar是否通过VM验证阶段。该模型可以向VM报告错误(以其术语表示),VM可以将它们转换为用户域术语,就像VM对值所做的那样。

您需要在两个地方进行验证,因为验证类型不同 - 在VM中进行简单的百分比验证,但可能在模型中进行更复杂的验证,同时考虑其他值等。