2013-11-02 5 views
3

Есть ли способ реализовать идею доменов данных (на уровне свойств) внутри класса, который используется как модель в представлении в ASP.Net MVC 4?Есть ли способ повторно использовать аннотации данных?

Рассмотрим этот код:

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; } 
} 

Вот LoginProfileModel в для ASP.Net MVC 4. Он использует множество аннотаций метаданных/данных, так что я могу создать чистый вид с этим кодом:

@model myWebSite.Areas.People.Models.LoginProfileModel 

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

Я использую идею «ИД входа» и «Пароль» в нескольких режимах и, следовательно, более чем в одной модели представления. Я хочу иметь возможность определять атрибуты, которые использует Пароль, или, возможно, сам Пароль со всеми его аннотациями данных в одном месте, чтобы я мог повторно использовать все эти определения там, где это необходимо, вместо того, чтобы выполнять их каждый раз, когда они используются:

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

Возможно ли это каким-то образом?

ответ

3

Следующие атрибуты влияют на процесс проверки вашего представления.

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

Для атрибутов проверки, вы можете создать класс, как это:

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; 
     } 
    } 

Вы можете использовать его следующим образом:

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

Два других атрибутов, которые Вы упомянули непосредственно полученный из класса Attribute, и я не думаю, что есть способ объединить их в один атрибут.

В ближайшее время я обновляю вас.

Итак, теперь мы остались с:

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

EDIT:

Согласно этому сообщению: Composite Attribute, это не представляется возможным объединить атрибуты.

+0

Замечательно, что это лучший ответ после того, как он некоторое время натыкался на него. Это позволяет мне централизовать логику проверки, которая в конечном итоге является тем, что мне нужно. – Elenesski

+0

Хорошая идея для разделения проверки поля. Было бы здорово, если бы мы могли использовать многоразовую технику '[DisplayName]. –

1

Вы можете сделать это, используя класс buddy, который предоставляет метаданные для вашей модели представления. Как так:

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; } 
} 

Тогда ваш вид модели:

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; } 
} 

Обратите внимание на использовании partial в определениях классов. Это то, что позволяет этому подходу работать. Одно предостережение, помимо очевидной проблемы с DRY, заключается в том, что я считаю, что класс метаданных должен находиться в том же пространстве имен, что и ваши модели просмотра, иначе он жалуется. Помимо этого, это должно делать то, что вы хотите.

0

В качестве следствия ответа Джона Х вы можете просто использовать наследование и сделать так, чтобы эти модели представлений, которые имеют «идею LogonId и пароль», наследуются от этой модели базового представления. Это позволило бы решить проблемы 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;} 
} 

Сейчас в SomeOtherClassThatNeedsLoginInfo, эти свойства и связанные с ними DataAnnotations будут доступны для вас.

Другой идеей было бы просто передать этот LoginInfo как свойство на других ваших моделях.

public SomeOtherClassThatNeedsLoginInfo{ 

      public string Property {get;set;} 

      public LoginProfileModel LoginModel {get;set;} 
    } 
Смежные вопросы