Я работаю над приложением MVC2 и хочу установить maxlength атрибуты вводов текста.
Я уже определил атрибут stringlength на Объекте модели с помощью аннотирований данных, и он проверяет длину вводимых строк правильно.
Я не хочу повторять ту же установку в своих представлениях путем установки макс. атрибута длины вручную, когда модель уже имеет информацию. Там какой-либо путь состоит в том, чтобы сделать это?
Фрагменты кода ниже:
Из модели:
[Required, StringLength(50)]
public string Address1 { get; set; }
От представления:
<%= Html.LabelFor(model => model.Address1) %>
<%= Html.TextBoxFor(model => model.Address1, new { @class = "text long" })%>
<%= Html.ValidationMessageFor(model => model.Address1) %>
То, что я не хочу делать:
<%= Html.TextBoxFor(model => model.Address1, new { @class = "text long", maxlength="50" })%>
Я хочу получить этот вывод:
<input type="text" name="Address1" maxlength="50" class="text long"/>
Там какой-либо путь состоит в том, чтобы сделать это?
Я не знаю, как добиться этого, не прибегая к рефлексии. Вы могли бы написать вспомогательный метод:
public static MvcHtmlString CustomTextBoxFor<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression,
object htmlAttributes
)
{
var member = expression.Body as MemberExpression;
var stringLength = member.Member
.GetCustomAttributes(typeof(StringLengthAttribute), false)
.FirstOrDefault() as StringLengthAttribute;
var attributes = (IDictionary<string, object>)new RouteValueDictionary(htmlAttributes);
if (stringLength != null)
{
attributes.Add("maxlength", stringLength.MaximumLength);
}
return htmlHelper.TextBoxFor(expression, attributes);
}
который можно использовать следующим образом:
<%= Html.CustomTextBoxFor(model => model.Address1, new { @class = "text long" })%>
Если вы хотите, чтобы это работало с классом метаданных, вам необходимо использовать следующий код. Я знаю, что это некрасиво, но он выполняет свою работу и избавляет вас от необходимости писать свои свойства maxlength как в классе Entity, так и в представлении:
public static MvcHtmlString TextBoxFor2<TModel, TProperty>
(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression,
object htmlAttributes = null
)
{
var member = expression.Body as MemberExpression;
MetadataTypeAttribute metadataTypeAttr = member.Member.ReflectedType
.GetCustomAttributes(typeof(MetadataTypeAttribute), false)
.FirstOrDefault() as MetadataTypeAttribute;
IDictionary<string, object> htmlAttr = null;
if(metadataTypeAttr != null)
{
var stringLength = metadataTypeAttr.MetadataClassType
.GetProperty(member.Member.Name)
.GetCustomAttributes(typeof(StringLengthAttribute), false)
.FirstOrDefault() as StringLengthAttribute;
if (stringLength != null)
{
htmlAttr = new RouteValueDictionary(htmlAttributes);
htmlAttr.Add("maxlength", stringLength.MaximumLength);
}
}
return htmlHelper.TextBoxFor(expression, htmlAttr);
}
Пример класса :
[MetadataType(typeof(Person.Metadata))]
public partial class Person
{
public sealed class Metadata
{
[DisplayName("First Name")]
[StringLength(30, ErrorMessage = "Field [First Name] cannot exceed 30 characters")]
[Required(ErrorMessage = "Field [First Name] is required")]
public object FirstName { get; set; }
/* ... */
}
}
Я использую CustomModelMetaDataProvider для достижения этого
Шаг 1. Добавьте новый класс CustomModelMetadataProvider
public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata CreateMetadata(
IEnumerable<Attribute> attributes,
Type containerType,
Func<object> modelAccessor,
Type modelType,
string propertyName)
{
ModelMetadata metadata = base.CreateMetadata(attributes,
containerType,
modelAccessor,
modelType,
propertyName);
//Add MaximumLength to metadata.AdditionalValues collection
var stringLengthAttribute = attributes.OfType<StringLengthAttribute>().FirstOrDefault();
if (stringLengthAttribute != null)
metadata.AdditionalValues.Add("MaxLength", stringLengthAttribute.MaximumLength);
return metadata;
}
}
Шаг 2. В Global.asax Зарегистрируйте CustomModelMetadataProvider
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ModelMetadataProviders.Current = new CustomModelMetadataProvider();
}
Шаг 3. В Views / Shared / EditorTemplates Добавьте частичное представление под названием String.ascx
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%if (!ViewData.ModelMetadata.AdditionalValues.ContainsKey("MaxLength")) { %>
<%: Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line" }) %>
<% } else {
int maxLength = (int)ViewData.ModelMetadata.AdditionalValues["MaxLength"];
%>
<%: Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line", MaxLength = maxLength })%>
<% } %>
Done ...
Edit. Шаг 3 может стать уродливым, если вы хотите добавить что-то в текстовое поле. В этом случае вы можете сделать следующее:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%
IDictionary<string, object> Attributes = new Dictionary<string, object>();
if (ViewData.ModelMetadata.AdditionalValues.ContainsKey("MaxLength")) {
Attributes.Add("MaxLength", (int)ViewData.ModelMetadata.AdditionalValues["MaxLength"]);
}
if (ViewData.ContainsKey("style")) {
Attributes.Add("style", (string)ViewData["style"]);
}
if (ViewData.ContainsKey("title")) {
Attributes.Add("title", (string)ViewData["title"]);
}
%>
<%: Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, Attributes)%>