2013-07-22 70 views
3

使用MVC4我需要從自定義ValidationAttribute中檢索當前ModelMetadata。原因是驗證屬性需要知道哪些其他屬性被附加到正在驗證的特定屬性。從驗證屬性中檢索模型元數據

在具體它檢查是否有一個UppercaseAttribute附屬於它;如果是這種情況,那麼它將執行不同的邏輯路徑。如果有可能從ValidationAttribute內搶ModelMetadata,我將使用下面的代碼來檢查它:

ModelMetadata.ContainerType 
    .GetProperty(ViewData.ModelMetadata.PropertyName) 
    .GetCustomAttributes(typeof(UppercaseAttribute), true) 

首先,是有可能從一個自定義ValidationAttribute內檢索ModelMetadata。其次,上述代碼是檢查屬性是否具有特定屬性的最佳實踐。

+0

您是否僅需要此特定型號的驗證屬性?如果是這樣的話,你可以發佈你的模型嗎? – ataravati

回答

4

這裏是你可以做什麼:

protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
{ 
    var model = validationContext.ObjectInstance; 

    var displayName = validationContext.DisplayName; 
    var propertyName = model.GetType().GetProperties() 
     .Where(p => p.GetCustomAttributes(false).OfType<DisplayAttribute>().Any(a => a.Name == displayName)) 
     .Select(p => p.Name).FirstOrDefault(); 
    if (propertyName == null) 
     propertyName = displayName; 

    var property = model.GetType().GetProperty(propertyName); 
    var uppercaseAttribute = property.GetCustomAttributes(typeof(UppercaseAttribute), false).SingleOrDefault() as UppercaseAttribute; 

    if (uppercaseAttribute != null) 
    { 
     // some code... 
    } 

    // return validation result... 
} 

出於某種原因,validationContext.MemberName始終爲空,所以你必須根據其顯示名稱來獲得屬性名。

+0

太棒了!這幾乎是我得到的地方,除了由於validationContext.MemberName爲空而導致我無法獲取屬性名稱之外。我猜如果顯示名稱爲空,那麼它將默認爲屬性名稱? – Jake

+0

是的,如果沒有顯示名稱,validationContext.DisplayName將返回屬性名稱。 我的答案中的代碼唯一的問題是,如果兩個屬性具有相同的顯示名稱,它將無法正常工作,但通常情況並非如此。 – ataravati

+0

是的,我注意到了這一點,但我想不出在我的代碼中會發生這種情況。 – Jake

2

要回答你的第一個問題:是的。您可以訪問ValidationAttribute對象內的ModelMetadata對象。最簡單的方法是實現System.Web.Mvc.IMetadataAware接口。該接口有一個名爲OnMetadataCreated的方法,它將在驗證屬性對象上的IsValid方法之前調用。此方法用於接收當前的ModelMetadata對象。以下代碼演示了用法:

public class MyCustomValidationAttribute : ValidationAttribute, IMetadataAware 
    { 
     private readonly object _typeId = new object(); 
     private ModelMetadata _metadata; 

     public MyCustomValidationAttribute() 
     { 
     } 

     public override object TypeId 
     { 
      get 
      { 
       return _typeId; 
      } 
     } 

     protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
     { 
      //Do something with the meta data 
      string propertyName = _metadata.PropertyName; 

      return ValidationResult.Success; 
     } 

     public void OnMetadataCreated(ModelMetadata metadata) 
     { 
      _metadata = metadata;   
     } 
    }