是否可以在ViewModel中重用DataAnnotations?

在我的MVC应用程序中,我在域模型中定义了DataAnnotations。 尽管在使用域模型时可以检索DataAnnotations属性作为Display等,但在ViewModel上使用相同属性并使用此ViewModel时,无法检索它们。 我认为再次在ViewModel中定义DataAnnotations似乎并不好。 那么,我应该遵循哪种方式?

领域模型:

public class Issue { [Key] public int ID { get; set; } [Required(ErrorMessage = "Required")] [Display(Name = "Project Number")] public int ProjectID { get; set; } [Required(ErrorMessage = "Required")] [Display(Name = "Issue Definition")] public string Description { get; set; } //... removed for brevity //Navigation Properties: public virtual ICollection FileAttachments { get; set; } } 

视图模型:

 public class IssueViewModel { public int ID { get; set; } public int ProjectID { get; set; } public string Description { get; set; } //... removed for brevity //Navigation Properties: public virtual ICollection FileAttachments { get; set; } } 

您可以创建一个新的伙伴类,其中包含有关属性和类的所有元数据。

 public partial class IssueMetadata { [Required(ErrorMessage = "Required")] [Display(Name = "Project Number")] public int ProjectID { get; set; } [Required(ErrorMessage = "Required")] [Display(Name = "Issue Definition")] public string Description { get; set; } } 

然后,我们必须通过MetadataType属性告诉MVC框架关于伙伴类,该属性将伙伴类的类型作为其参数。 伙伴类必须在同一名称空间中定义,并且还必须是partial类。

 [MetadataType(typeof(IssueMetadata))] public partial class IssueViewModel { //... public int ProjectID { get; set; } public string Description { get; set; } //... } [MetadataType(typeof(IssueMetadata))] public partial class Issue { [Key] public int ID { get; set; } public int ProjectID { get; set; } public string Description { get; set; } //... removed for brevity //Navigation Properties: public virtual ICollection FileAttachments { get; set; } } 

附加说明:
如果IssueMetadataIssue (或IssueViewModel )类位于不同的程序集中,那么您可以在运行时将类与其buddy类关联,如下所示:

 public class AssociatedMetadataConfig { public static void RegisterMetadatas() { RegisterPairOfTypes(typeof(Issue), typeof(IssueMetadata)); RegisterPairOfTypes(typeof(IssueViewModel), typeof(IssueMetadata)); } private static void RegisterPairOfTypes(Type mainType, Type buddyType) { AssociatedMetadataTypeTypeDescriptionProvider typeDescriptionProvider = new AssociatedMetadataTypeTypeDescriptionProvider(mainType, buddyType); TypeDescriptor.AddProviderTransparent(typeDescriptionProvider, mainType); } } 

并且,只需在global.asax调用此静态方法:

 AssociatedMetadataConfig.RegisterMetadatas(); 

@StephenMuecke是对的。 DomainModel属性和ViewModel属性不同,您可以在模型中单独使用它们。 但如果我是你,我会在这种情况下使用。 您可以为ViewModel创建Partial类,并从此ViewModel类inheritance您的DomainModel。

喜欢:

 public class IssueVM { [Key] public int ID { get; set; } [Required(ErrorMessage = "Required")] [Display(Name = "Project Number")] public int ProjectID { get; set; } [Required(ErrorMessage = "Required")] [Display(Name = "Issue Definition")] public string Description { get; set; } //... removed for brevity //Navigation Properties: public virtual ICollection FileAttachments { get; set; } } public class IssueDM : IssueVM { // Other Fields } 

这样,您就拥有了一个ViewModel(较少字段)的基类和一个包含更多DB操作字段的较大类。 您的ViewModel数据注释属性也以这种方式在DomainClass中inheritance。

我并不认为这是最好的方式,但我使用它并且工作正常。