2012-04-30 15 views
11

Say Mam modelu jak tenklienta Html pomocnika, który może przeglądać DataAnnotations

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

} 

Chcę utworzyć pomocnika html jak poniżej:

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

tak, że wypluwa pole tekstowe z poprawny format plugin jQuery Vaidation aby móc zweryfikować, tak:

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

z moich badań, wydaje się, że nie ma sposób na powtórzenie wszystkich adnotacji danych w MetaDataModel, dzięki czemu mogę sprawdzić, które z nich mają zastosowanie do sprawdzania poprawności jQuery.

Jak mogę sobie wyobrazić, że pracuje w pseudo kod:

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

Jak mogę iść o osiągnięciu pomocnika takiego? Chcę, aby działała na adnotacjach danych, aby nie musieć duplikować literałów sprawdzania poprawności.

Na przykład, obecni pomocnicy Html, tacy jak TextEditorFor, dołączają atrybuty walidowalne do ich pól wyjściowych. Jak to robi i jak mogę stworzyć własną implementację?

Cheers

Odpowiedz

6

Można w ten prosty warunek:

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

UPDATE

zdefiniować pomocnika HTML:

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

stworzenia tej metody pomocnika:

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

Teraz to wykorzystać w 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>(); 

Teraz można sprawdzić atrybuty .... reszta jest prosta.

+0

Ale nie ma kolekcji MetaDataModel.Attributes. Jak mogę uzyskać listę wszystkich atrybutów, które może posiadać dowolny konkretny model? – Chris

+0

Zobacz moją aktualizację .. – Aliostad

+0

Zmieniono kod ValidationEditorFor tak, aby przechwycił właściwości ValidationAttribute z właściwości. Tak jak to było, szukał atrybutów na typie właściwości (string, int, cokolwiek). Kod działa świetnie teraz dzięki! :) – Chris

2

Lekko zmieniona i wyodrębniona w pomocnika.

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; 
     } 
    } 
} 
Powiązane problemy