Пользовательский помощник 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;
}
}
Как я могу найти помощника, подобного этому? Я хочу, чтобы он работал над аннотациями данных, так что мне не нужно дублировать литералы проверки.
Например, текущие Html-помощники, такие как TextEditorFor, добавляют в свои выходные поля атрибуты validatable. Как это сделать и как я могу выполнить свою собственную реализацию?
Приветствия
Ответы
Ответ 1
Вы можете использовать это простое условие:
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>();
Теперь вы можете проверить атрибуты.... отдых прост.
Ответ 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;
}
}
}