C# 如何忽略MetadataType属性中缺少的字段?

C# 如何忽略MetadataType属性中缺少的字段?,c#,asp.net-mvc,metadata,data-annotations,C#,Asp.net Mvc,Metadata,Data Annotations,我有映射到ViewModels的DTO。为了避免管理验证属性(和其他属性),我希望为单个类上的所有属性编写验证属性,并在ViewModels上重用它。但是,当我尝试在没有DTO所有属性的ViewModel上使用元数据(所有属性都是真的…)时,它会给我一个System.invalidoOperationException异常 例外情况: Le type de métadonnées associépour Le type“MyProject.EntityViewModel”contient les

我有映射到ViewModels的DTO。为了避免管理验证属性(和其他属性),我希望为单个类上的所有属性编写验证属性,并在ViewModels上重用它。但是,当我尝试在没有DTO所有属性的ViewModel上使用元数据(所有属性都是真的…)时,它会给我一个
System.invalidoOperationException
异常

例外情况:

Le type de métadonnées associépour Le type“MyProject.EntityViewModel”contient les propriétés ou champs inconus suivants:另一个属性。Vérifiez que les noms de ces membres contractor aux noms des propriétés du type principal.

谷歌翻译:

类型“MyProject.EntityViewModel”的类型关联元数据包含以下未知属性或字段:AnotherProperty。验证这些成员的名称是否与主类型属性的名称匹配。

简化示例:

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没有另一个属性,因此它将引发异常。有什么方法可以防止这种情况发生吗?

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

无论你想出什么样的解决方案来阻止抛出异常,这都将是一次黑客攻击

根据评论更新

我不想在需要更改验证规则时搜索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; }
}
然而,这带来了一个问题。如果要继承另一组验证属性,该怎么办?您不能,因为我们仅限于从一个类继承。我们也不能从接口继承数据注释:

产品团队不希望实现此功能,主要原因有两个:

  • 与DataAnnotations.Validator的一致性
  • 与ASP.NETMVC中验证行为的一致性

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

  • (来源:)

    那么,如果您需要对特定视图进行
    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; }
    }
    
    你知道这是怎么回事吗?这会变成一团乱麻。因此,正如我前面所说的,只有当您的属性适合定义良好的组并在其中使用时,这才有效,但在您的场景中,情况似乎并非如此


    最后,让我链接到几年前Mystere Man发布的我一直喜欢的答案:

    应用于属性的验证规则应该应用于所有地方。如果您验证一个字符串的长度在5到10个字符之间,并且您的数据库字段有10个字节,那么为什么您会允许某人写入超过10个字节的数据?此外,正如我在问题中所说,我知道它不应该出现在DTO上。这只是一个简单的例子。因此,如果我碰巧编写了一个特殊视图,但dans不希望进行验证,我将不会在其上使用MetadataType属性。@Pluc
    如果您验证一个字符串在5到10个字符之间,并且您的数据库字段有10个字节,为什么您会允许某人写入超过10个字节的内容?
    对于一个简单的字符串,这可能是正确的,但你的模型上的每个属性都不是这样。我在这里看到了很多问题,人们想要
    RequiredIf
    功能。(就是这样一个例子。)更新了问题,以显示我试图实现的内容的更完整版本。关于RequiredIf,这将是一个特定于视图的验证。我的“EntityInputValidation”不需要。它将出现在我的ViewModel上。更新问题。@Pluc请使用实际实体和DTO更新您的问题,以保持清晰。如果
    AnotherProperty
    仅为实体,则不能根据需要使用注释
    AnotherProperty
    的元数据并在DTO上使用,因为DTO不包含该属性。但是,您可以尝试创建具有共享属性的基本元数据类,并使用实体或DTO特定属性对其进行扩展,并在
    MetaDataType
    属性中应用扩展类。