2012-04-30 17 views
11

decir que tengo un modelo como esteHTML personalizada de ayuda que puede navegar DataAnnotations

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

} 

Quiero crear un asistente de HTML así:

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

para que escupe un campo de texto con el formato correcto para jQuery Vaidation plugin para poder validar, así:

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

de mi investigación, parece que no hay forma de iterar sobre todas las anotaciones de datos en un MetaDataModel para que pueda verificar cuáles son aplicables a jQuery Validation.

Cómo visualizo que trabajan en pseudo código:

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

¿Cómo podría ir sobre la realización de un ayudante de esta manera? Quiero que funcione en las anotaciones de datos para que no tenga que duplicar los literales de validación.

Por ejemplo, los helpers Html actuales, como TextEditorFor, añaden atributos validables a sus campos de salida. ¿Cómo hace esto y cómo puedo hacer mi propia implementación?

Saludos

Respuesta

6

Usted puede utilizar este simple condición:

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

ACTUALIZACIÓN

Definir un ayudante HTML:

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

crear este método de ayuda:

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

Ahora utilice esto en 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>(); 

Ahora puede comprobar los atributos .... resto es fácil.

+0

Pero no hay colección de MetaDataModel.Attributes. ¿Cómo puedo obtener una lista de todos los atributos que cualquier modelo en particular puede tener? – Chris

+0

Ver mi actualización ... – Aliostad

+0

Modifiqué el código ValidationEditorFor para que tome ValidationAttribute de la propiedad. Como estaba, estaba buscando los atributos en el Tipo de la propiedad (cadena, int, lo que sea). El código está funcionando bien ahora gracias! :) – Chris

2

Ligeramente alterado y extraído en un ayudante.

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