2012-04-30 13 views
11

Sagen wir, ich habe ein Modell wie diesesbenutzerdefinierte HTML-Helfer, der DataAnnotations

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

} 

durchsuchen kann ich ein HTML-Helfer wie diese erstellen möchten:

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

, so dass es ein Textfeld spuckt mit das richtige Format für jQuery Plugin Vaidation Lage sein, dies zu überprüfen, wie:

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

Aus meiner Forschung scheint es, dass es keine Möglichkeit, über alle Datenanmerkungen in einem MetaDataModel zu iterieren, so dass ich prüfen kann, welche für die jQuery-Validierung anwendbar sind.

Wie stelle ich mich es funktioniert in Pseudo-Code:

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

Wie kann ich mich über einen Helfer wie dieses Ziel zu erreichen? Ich möchte, dass es an Datenanmerkungen arbeitet, damit ich die Validierungsliterale nicht duplizieren muss.

Zum Beispiel, die aktuellen HTML-Helfer wie TextEditorFor fügen validierbare Attribute an ihre Ausgabefelder an. Wie macht es das und wie kann ich meine eigene Implementierung machen?

Prost

Antwort

6

können Sie diese einfache Bedingung verwenden:

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

UPDATE

definieren eine HTML-Helfer:

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

diese Hilfsmethode erstellen:

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

dies nun in ValidationEditorFor verwenden:

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

Jetzt können Sie die Attribute überprüfen .... Rest ist einfach.

+0

Aber es gibt keine MetaDataModel.Attributes-Auflistung. Wie kann ich eine Liste aller Attribute erhalten, die ein bestimmtes Modell haben kann? – Chris

+0

Siehe mein Update .. – Aliostad

+0

Ich änderte den ValidationEditorFor-Code, so dass es das ValidationAttribute von der Eigenschaft ergreift. So wie es war, suchte es nach den Attributen des Typs der Eigenschaft (string, int, was auch immer). Der Code funktioniert jetzt großartig! :) – Chris

2

Leicht verändert und in einen Helfer extrahiert.

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