атрибут maxlength текстового поля от DataAnnotations StringLength у Asp. Сетевой MVC

Я работаю над приложением 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"/>

Там какой-либо путь состоит в том, чтобы сделать это?

78
задан Pervez Choudhury 7 November 2012 в 15:23
поделиться

3 ответа

Я не знаю, как добиться этого, не прибегая к рефлексии. Вы могли бы написать вспомогательный метод:

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" })%>
52
ответ дан 24 November 2019 в 10:35
поделиться

Если вы хотите, чтобы это работало с классом метаданных, вам необходимо использовать следующий код. Я знаю, что это некрасиво, но он выполняет свою работу и избавляет вас от необходимости писать свои свойства 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; }

    /* ... */
  }
}
8
ответ дан 24 November 2019 в 10:35
поделиться

Я использую 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)%>
20
ответ дан 24 November 2019 в 10:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: