2012-04-30 23 views
11

說我有這樣的自定義HTML幫助,可以瀏覽DataAnnotations

public class User 
{ 
    [Required] 
    [StringLength(14, ErrorMessage = "Can only be 14 characters long")] 
    public string UserName; 

} 

一個模式,我想創建一個HTML輔助這樣的:

@Html.ValidatableEditorFor(m => m.UserName) 

,使其吐出了一個文本字段正確的格式jQuery Vaidation插件能夠驗證,像這樣:

<input type="text" class="required" maxlength="14" /> 

從我的研究,似乎沒有方法遍歷MetaDataModel中的所有數據註釋,以便我可以檢查哪些適用於jQuery驗證。

如何我想象它的僞代碼工作:

var tag = new TagBuilder("input"); 
    tag.mergeAttribute("type", "text"); 
    foreach(var attribute in metadata.attributes) 
    { 
     CheckForValidatableAttribute(attribute, tag); 
    } 

... 
    private void CheckForValidatableAttribute(DataAnnotation attribute, TagBuilder tag) 
    { 
     switch(attribute.type) 
     { 
      case Required: 
      tag.addClass("required"); 
      break; 
      case StringLength 
      tag.mergeAttribute("maxlength", attribute.value) 
      break; 
     } 
    } 

我怎麼可能去實現這樣的幫手?我希望它能夠處理數據註釋,這樣我就不必複製驗證字面值。

例如,像TextEditorFor這樣的當前Html幫助器會將validatable屬性附加到它們的輸出字段。它如何做到這一點,我怎樣才能做出自己的實現?

乾杯

回答

6

你可以使用這個簡單的條件:

if(attribute.Type is ValidationAttribute) 
{ 
    string className = attribute.Type.Name.Replace("Attribute", "").ToLower(); 
} 

UPDATE

定義的HTML幫助:

public static MvcHtmlString ValidationEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, 
     Expression<Func<TModel, TProperty>> expression) 
{ 
    .... 
} 

創建這個輔助方法:

private static string GetPropertyNameFromExpression<TModel, TProperty>(HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) 
{ 
    MemberExpression memberExpression = expression.Body as MemberExpression; 
    if (memberExpression == null) 
     throw new InvalidOperationException("Not a memberExpression"); 

    if (!(memberExpression.Member is PropertyInfo)) 
     throw new InvalidOperationException("Not a property"); 

    return memberExpression.Member.Name; 
} 

現在ValidationEditorFor使用:

var propertyName = GetPropertyNameFromExpression(htmlHelper, expression); 
var propertyType = typeof(TModel).GetProperties().Where(x=>x.Name == propertyName).First().PropertyType; 
var attributes = propertyType.GetCustomAttributes(true).OfType<ValidationAttribute>(); 

現在你可以檢查屬性....都好辦。

+0

但是沒有MetaDataModel.Attributes集合。我如何獲得任何特定模型可能具有的所有屬性的列表? – Chris

+0

查看我的更新.. – Aliostad

+0

我更改了ValidationEditorFor代碼,以便它從屬性中獲取ValidationAttribute。實際上,它正在尋找屬性類型(string,int,whatever)上的屬性。代碼現在工作很好,謝謝! :) – Chris

2

略微改變並提取成幫手。

using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Reflection; 

namespace Payntbrush.Infrastructure.Web.Mvc 
{ 
    public static class ReflectionHelper 
    { 
     public static IEnumerable<ValidationAttribute> GetAttributes<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression) 
     { 
      Type type = typeof(TModel); 
      var prop = type.GetProperty(GetPropertyNameFromExpression(expression)); 
      return prop.GetCustomAttributes(true).OfType<ValidationAttribute>(); 
     } 


     private static string GetPropertyNameFromExpression<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression) 
     { 
      var memberExpression = expression.Body as MemberExpression; 
      if (memberExpression == null) 
       throw new InvalidOperationException("Not a memberExpression"); 

      if (!(memberExpression.Member is PropertyInfo)) 
       throw new InvalidOperationException("Not a property"); 

      return memberExpression.Member.Name; 
     } 
    } 
}