简体   繁体   English

有没有办法重用数据注释?

[英]Is there a way to reuse data annotations?

Is there a way to implement the idea of a data domains (at a property level) inside of a class that is used as a model in a view in ASP.Net MVC 4? 有没有办法在ASP.Net MVC 4中的视图中用作模型的类内部实现数据域(在属性级别)的概念?

Consider this code: 考虑以下代码:

public class LoginProfileModel {

    [DisplayName("Login ID")]
    [Required(ErrorMessage = "Login ID is required.")]
    public string LogonID { get; set; }

    [DisplayName("Password")]
    [Required(ErrorMessage = "Password cannot be blank.")]
    [StringLength(20, MinimumLength = 3)]
    [DataType(DataType.Password)]
    public string Password { get; set; }
}

Here is a LoginProfileModel in for ASP.Net MVC 4. It uses a variety of metadata/data annotations so that I can create a clean view with this code: 这是ASP.Net MVC 4中的LoginProfileModel。它使用各种元数据/数据注释,以便我可以使用以下代码创建一个干净的视图:

@model myWebSite.Areas.People.Models.LoginProfileModel

@using ( Html.BeginForm( "Index" , "Login" ) ) {
    @Html.ValidationSummary()
    @Html.EditorForModel()
    <input type="submit" value="Login" />
}

I use the idea of a "Login ID" and a "Password" in more than one view, and therefore, in more than one view model. 我在多个视图中使用“登录ID”和“密码”的概念,因此,在多个视图模型中使用。 I want to be able to define the attributes that a Password uses, or possibly the Password itself with all of it's data annotations in a single location so that I can reuse all those definitions where needed, rather than respecifying them every time they are used: 我希望能够在一个位置定义密码使用的属性,或者可能是密码本身以及所有这些数据注释,以便我可以在需要时重用所有这些定义,而不是每次使用时重新指定它们:

    [DisplayName("Password")]
    [Required(ErrorMessage = "Password cannot be blank.")]
    [StringLength(20, MinimumLength = 3)]
    [DataType(DataType.Password)]
    public string Password { get; set; }

Is that possible some way? 这有可能吗?

The following attributes affect the validation process of your View. 以下属性会影响View的验证过程。

[Required(ErrorMessage = "Password cannot be blank.")]
[StringLength(20, MinimumLength = 3)]

For the Validation attributes, you can create a class like this: 对于Validation属性,您可以创建如下的类:

public class PasswordRuleAttribute : ValidationAttribute
    {    
        public override bool IsValid(object value)
        {

            if (new RequiredAttribute { ErrorMessage = "Password cannot be blank." }.IsValid(value) && new StringLengthAttribute(20) { MinimumLength=3 }.IsValid(value) )
                return true;

            return false;
        }
    }

You can use it as follows: 您可以按如下方式使用它:

[PasswordRule]
public string Password{get;set;}

The other two attributes that you mentioned are Directly derived from the Attribute class, and I don't think there's a way to consolidate them into a single attribute. 您提到的其他两个属性是直接从Attribute类派生的,我认为没有办法将它们合并为单个属性。

I'll update you with an edit soon. 我很快就会通过编辑为您更新。

So now we're left with: 所以现在我们离开了:

[DisplayName("Password")]
[DataType(DataType.Password)]
[PasswordRule]
public string Password{get;set;}

EDIT: 编辑:

According to this post: Composite Attribute , it's not possible to merge attributes. 根据这篇文章: 复合属性 ,不可能合并属性。

You can do this using a buddy class, which provides metadata for your view model. 您可以使用伙伴类来执行此操作,该类为视图模型提供元数据。 Like so: 像这样:

public partial class LogonMetaData
{
    [DisplayName("Login ID")]
    [Required(ErrorMessage = "Login ID is required.")]
    public string LogonID { get; set; }

    [DisplayName("Password")]
    [Required(ErrorMessage = "Password cannot be blank.")]
    [StringLength(20, MinimumLength = 3)]
    [DataType(DataType.Password)]
    public string Password { get; set; }
}

Then your view models: 然后你的视图模型:

using System.ComponentModel.DataAnnotations;

[MetadataType(typeof(LogonMetaData))]
public partial class FirstViewModel
{
    public string LogonID { get; set; }
    public string Password { get; set; }
}

using System.ComponentModel.DataAnnotations;

[MetadataType(typeof(LogonMetaData))]
public partial class SecondViewModel
{
    public string LogonID { get; set; }
    public string Password { get; set; }
}

Note the use of partial in the class definitions. 注意在类定义中使用partial This is what allows this approach to work. 这是允许这种方法工作的原因。 One caveat, other than the obvious problem with DRY, is that I believe the metadata class has to reside in the same namespace as your view models, else it complains. 除了DRY的明显问题之外,一个警告是,我认为元数据类必须与视图模型位于相同的命名空间中,否则它会抱怨。 Other than that, this should do what you want. 除此之外,这应该做你想要的。

As a corollary to John H's answer, you could just use inheritance and make those view models that have the "idea of a LogonId and password" inherit from that base view model. 作为John H的答案的必然结果,您可以使用继承并使那些具有“LogonId和密码的概念”的视图模型继承自该基本视图模型。 This would solve the MetaData issues that were mentioned in the previous answer. 这将解决前一个答案中提到的MetaData问题。

      public class LoginProfileModel {

        [DisplayName("Login ID")]
        [Required(ErrorMessage = "Login ID is required.")]
        public string LogonID { get; set; }

        [DisplayName("Password")]
        [Required(ErrorMessage = "Password cannot be blank.")]
        [StringLength(20, MinimumLength = 3)]
        [DataType(DataType.Password)]
        public string Password { get; set; }
    }

    public SomeOtherClassThatNeedsLoginInfo : LoginProfileModel{

         public string Property {get;set;}
}

Now in the SomeOtherClassThatNeedsLoginInfo, those properties and their related DataAnnotations will be available to you. 现在,在SomeOtherClassThatNeedsLoginInfo中,您可以使用这些属性及其相关的DataAnnotations。

Another idea would be just to pass that LoginInfo as a property on your other view models. 另一个想法是将LoginInfo作为属性传递给其他视图模型。

public SomeOtherClassThatNeedsLoginInfo{

             public string Property {get;set;}

             public LoginProfileModel LoginModel {get;set;}
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM