2012-04-30 30 views
11

Nói rằng tôi có một mô hình như thế nàyTuỳ chỉnh Html helper có thể duyệt DataAnnotations

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

} 

Tôi muốn tạo ra một helper Html như thế này:

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

để nó spits ra một trường văn bản với định dạng đúng cho plugin jQuery Vaidation để có thể xác thực, như sau:

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

Từ nghiên cứu của tôi, có vẻ như không có cách để lặp qua tất cả chú thích dữ liệu trong MetaDataModel để tôi có thể kiểm tra xem cái nào có thể áp dụng cho Xác thực jQuery.

Làm thế nào tôi hình dung nó làm việc trong mã giả:

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

Làm thế nào tôi có thể đi về việc đạt được một helper như thế này? Tôi muốn nó hoạt động trên các chú thích dữ liệu để tôi không phải sao chép các chữ xác nhận.

Ví dụ: người trợ giúp Html hiện tại như TextEditorFor làm gắn các thuộc tính hợp lệ vào trường đầu ra của chúng. Làm thế nào để làm điều này, và làm thế nào tôi có thể thực hiện của riêng tôi?

Cheers

Trả lời

6

Bạn có thể sử dụng điều kiện đơn giản này:

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

CẬP NHẬT

Xác định một helper Html:

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

Tạo phương pháp helper này:

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

Bây giờ sử dụng này trong 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>(); 

Bây giờ bạn có thể kiểm tra các thuộc tính .... còn lại là dễ dàng.

+0

Nhưng không có bộ sưu tập MetaDataModel.Attributes. Làm cách nào để có danh sách tất cả các thuộc tính mà bất kỳ mô hình cụ thể nào có thể có? – Chris

+0

Xem cập nhật của tôi .. – Aliostad

+0

Tôi đã thay đổi mã ValidationEditorFor để nó lấy được thuộc tính ValidationAttribute từ thuộc tính. Vì nó đã được, nó đã được tìm kiếm các thuộc tính về Loại tài sản (chuỗi, int, bất cứ điều gì). Mã đang làm việc tuyệt vời ngay bây giờ nhờ! :) – Chris

2

Hơi bị thay đổi và trích xuất thành người trợ giúp.

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