【问题标题】:How can I ignore missing fields from the MetadataType attribute?如何忽略 MetadataType 属性中缺少的字段?
【发布时间】:2013-11-19 06:22:25
【问题描述】:

我有映射到 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,所以会抛出异常。有没有办法防止这种情况发生?

【问题讨论】:

    标签: c# asp.net-mvc metadata data-annotations


    【解决方案1】:

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

    几乎无论您想出什么解决方案来阻止抛出异常都是一种黑客行为。

    按 cmets 更新

    每当我们必须更改验证规则时,我不想搜索 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; }
    }
    

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

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

    【讨论】:

    • 应用于属性的验证规则应该适用于任何地方。如果您验证一个字符串介于 5 到 10 个字符之间,并且您的数据库字段有 10 个字节,那么您为什么要允许某人写入超过 10 个字节?此外,就像我在问题中所说的那样,我知道它不应该出现在 DTO 上。这只是一个简化的例子。所以如果我碰巧写了一个特殊的视图dans不想验证,我不会使用MetadataType属性就可以了。
    • @Pluc If you validate that a string is between 5 and 10 characters, and your database field has 10 bytes, why would you ever allow someone to write over 10 bytes? 对于一个简单的字符串可能是这样,但对于模型上的每个属性,情况并非如此。我在这里看到了很多想要RequiredIf 功能的人的问题。 (Here 就是这样一个例子。)
    • 更新了问题以显示我想要实现的更完整的版本。
    • 关于RequiredIf,这将是特定于视图的验证。我的“EntityInputValidation”没有RequiredIf。它将在我的 ViewModel 上。更新问题。
    • @Pluc 请用 actual 实体和 DTO 更新您的问题,以便清楚起见。如果AnotherProperty 是仅限实体的,则您不能根据需要使用注释AnotherProperty 的元数据并将其用于您的DTO,因为您的DTO 不包含该属性。但是,您可以尝试创建具有共享属性的基本元数据类,并使用实体或 DTO 特定属性对其进行扩展,并在 MetaDataType 属性中应用扩展类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-15
    • 1970-01-01
    • 2011-02-09
    相关资源
    最近更新 更多