是否可以在ViewModel中重用DataAnnotations?

Jac*_*ack 2 c# asp.net-mvc domain-model data-annotations asp.net-mvc-viewmodel

在我的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<FileAttachment> FileAttachments { get; set; }
}
Run Code Online (Sandbox Code Playgroud)


视图模型:

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<FileAttachment> FileAttachments { get; set; }      
}
Run Code Online (Sandbox Code Playgroud)

Far*_*yev 5

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

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; }
}
Run Code Online (Sandbox Code Playgroud)

然后,我们必须通过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<FileAttachment> FileAttachments { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

AssociatedMetadataConfig.RegisterMetadatas();
Run Code Online (Sandbox Code Playgroud)