Полный пример кода для ответа tvanfosson:
Модель:
public class Product
{
public int Id { get; set; }
[MaxLength(200)]
public string Name { get; set; }
EditorTemplates \ String.cshtml
@model System.String
@{
var metadata = ViewData.ModelMetadata;
var prop = metadata.ContainerType.GetProperty(metadata.PropertyName);
var attrs = prop.GetCustomAttributes(false);
var maxLength = attrs.OfType<System.ComponentModel.DataAnnotations.MaxLengthAttribute>().FirstOrDefault();
}
<input id=@Html.IdForModel()@(metadata.IsRequired ? " required" : "")@(maxLength == null ? "" : " maxlength=" + maxLength.Length) />
Вывод HTML:
<input id=Name maxlength=200 />
Ужасно, но это работает. Теперь давайте отвлечемся от этого и немного очистим. Вспомогательный класс:
public static class EditorTemplateHelper
{
public static PropertyInfo GetPropertyInfo(ViewDataDictionary viewData)
{
var metadata = viewData.ModelMetadata;
var prop = metadata.ContainerType.GetProperty(metadata.PropertyName);
return prop;
}
public static object[] GetAttributes(ViewDataDictionary viewData)
{
var prop = GetPropertyInfo(viewData);
var attrs = prop.GetCustomAttributes(false);
return attrs;
}
public static string GenerateAttributeHtml(ViewDataDictionary viewData, IEnumerable<Delegate> attributeTemplates)
{
var attributeMap = attributeTemplates.ToDictionary(t => t.Method.GetParameters()[0].ParameterType, t => t);
var attrs = GetAttributes(viewData);
var htmlAttrs = attrs.Where(a => attributeMap.ContainsKey(a.GetType()))
.Select(a => attributeMap[a.GetType()].DynamicInvoke(a));
string s = String.Join(" ", htmlAttrs);
return s;
}
}
Шаблон редактора:
@model System.String
@using System.ComponentModel.DataAnnotations;
@using Brass9.Web.Mvc.EditorTemplateHelpers;
@{
var metadata = ViewData.ModelMetadata;
var attrs = EditorTemplateHelper.GenerateAttributes(ViewData, new Delegate[] {
new Func<StringLengthAttribute, string>(len => "maxlength=" + len.MaximumLength),
new Func<MaxLengthAttribute, string>(max => "maxlength=" + max.Length)
});
if (metadata.IsRequired)
{
attrs.Add("required");
}
string attrsHtml = String.Join(" ", attrs);
}
<input type=text id=@Html.IdForModel() @attrsHtml />
Таким образом, вы передаете массив делегатов, и для каждой записи используйте Func<AttributeTypeGoesHere, string>
, а затем возвращаете любую строку HTML, которую вы хотите для каждого атрибута.
Это на самом деле хорошо разделяет - вы можете отобразить только те атрибуты, которые вам нужны, вы можете отобразить разные наборы для разных частей одного и того же HTML, и конечное использование (например, @attrsHtml
) не повредит читабельности шаблона.