1

我有映射到 ViewModel 的 DTO。为了避免必须管理验证属性(和其他属性),我想为单个类上的所有属性编写验证属性,并在我的 ViewModel 上重用它。但是,当我尝试在不具有 DTO 的所有属性的 ViewModel 上使用元数据(所有这些属性真的......)时,它给了我一个System.InvalidOperationException例外。

例外:

Le type de métadonnées associé pour le type 'MyProject.EntityViewModel' contient les propriétés ou champs inconnus suivants : AnotherProperty. Vérifiez que les noms de ces membres correspondent aux noms des propriétés du type principal.

谷歌翻译:

The type associated metadata for type 'MyProject.EntityViewModel' contains the following unknown properties or fields: AnotherProperty. Verify that the names of these members match the names of the properties of the main type.

简化示例:

public class Entity {
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }
}

public class EntityDTO {
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }
}

//This class is used to add validation attributes for input-related view models
public class EntityInputValidation {
    [Required]
    public string A { get; set; }

    [Required]
    public string B { get; set; }

    //Notice that we dont have a validation for C
}

//This class is a ViewModel used to create a new Entity
[MetadataType(typeof(EntityInputValidation))]
public class EntityCreateViewModel {
    //Required because we use the InputValidation metadata
    public string A { get; set; }

    //Notice that we do not have the B property here, even if we are using the Input Validation which has a required attribute for this property. This is where the exception comes from.

    //C is only required in this View/ViewModel
    [Required]
    public string C { get; set; }
}

因为 EntityViewModel 没有AnotherProperty,所以会抛出异常。有没有办法防止这种情况?

4

1 回答 1

2

我当然会重新考虑将这些注释直接放在您的实体上。正如您已经看到的,每当您需要在不需要遵守这些验证规则的视图中使用该实体时,这都会给您带来问题。如果添加更多使用您的实体的视图,从长远来看,这可能会变得更糟。

几乎无论你想出什么解决方案来阻止抛出异常都将是一个 hack。

根据评论更新

每当我们必须更改验证规则时,我不想搜索 20 个视图模型......我们目前有 2 个网站,很快就会有 3 个,它们是使用相同 DAL 和业务逻辑的解决方案的一部分。那是很多视图模型要保持更新。

这当然是一个有效的担忧,这也是一个有效的问题。问题更多的是没有明确定义的解决方案,至少我发现了。

看一下继承的思路,乍一看似乎是合理的。但是,只有当您的属性适合整齐的组时,这才会起作用,从您更新的问题看来,情况可能并非如此。

我们举一个简单的例子:

public class LoginValidation
{
    [Required]
    public string Username { get; set; }
    [Required]
    public string Password { get; set; }
}

然后,您可以从中派生视图模型:

public class ViewModelA : LoginValidation
{
    public string SomeOtherProperty { get; set; }
}

然而,这带来了一个问题。如果你想继承另一组验证属性怎么办?你不能,因为我们仅限于从一个类继承。我们也不能从接口继承数据注释:

产品团队不想实现这个功能,主要有两个原因:

  1. 与 DataAnnotations.Validator 的一致性
  2. 与 ASP.Net MVC 中的验证行为一致

    棘手的场景:一个类实现了两个具有相同属性但属性冲突的接口。哪个属性优先?

(来源:http ://social.msdn.microsoft.com/Forums/en-US/1748587a-f13c-4dd7-9fec-c8d57014632c/code-first-dataannotations-in-interfaces?forum=adonetefx )

那么,如果您需要LoginValidation对特定视图进行一些日期验证怎么办?您必须在中间类中创建一个继承链,以便能够从您的视图模型继承:

public class LoginAndDateValidation : LoginValidation
{
    [Required]
    public DateTime StartDate { get; set; }
    [Required]
    public DateTime EndDate { get; set; }
}

public class ViewModelA : LoginAndDateValidation
{
    public string SomeOtherProperty { get; set; }
}

你知道这是怎么回事吗?这将变成一团糟。因此,正如我之前所说,这仅在您的属性适合并用于定义明确的组时才有效,但在您的场景中似乎并非如此。

最后,让我链接到几年前我一直喜欢的神秘人发布的答案:https ://stackoverflow.com/a/8075115/729541

于 2013-11-07T14:50:03.150 回答