Атрибут MaxLength не генерує атрибути перевірки на стороні клієнта


83

У мене є курйозна проблема з перевіркою на стороні клієнта ASP.NET MVC3. У мене є такий клас:

public class Instrument : BaseObject
{
    public int Id { get; set; }

    [Required(ErrorMessage = "Name is required.")]
    [MaxLength(40, ErrorMessage = "Name cannot be longer than 40 characters.")]
    public string Name { get; set; }
}

На мій погляд:

<div class="editor-field">
    @Html.EditorFor(model => model.Name)
    @Html.ValidationMessageFor(model => model.Name)
</div>

І ось згенерований HTML, який я отримую для текстового поля для цього поля:

<input class="text-box single-line" data-val="true" data-val-required="Name is required." id="Name" name="Name" type="text" value="">

Ніяких ознак MaxLengthAttribute, але все інше, здається, працює.

Будь-які ідеї, що йде не так?

Відповіді:


151

Спробуйте використати [StringLength]атрибут:

[Required(ErrorMessage = "Name is required.")]
[StringLength(40, ErrorMessage = "Name cannot be longer than 40 characters.")]
public string Name { get; set; }

Це для цілей перевірки. Якщо ви хочете встановити, наприклад, атрибут maxlength на вході, ви можете написати власний постачальник метаданих анотацій даних, як показано в цій публікації, та налаштувати шаблони за замовчуванням .


3
Дуже дякую. Якщо хтось цікавиться, я перевірив, що EF Code First створює стовпець DB з максимальною довжиною, встановленою атрибутом StringLength. :)
Matt Jenkins

Але це не відповідь. Оскільки атрибут MinLength теж не працює
Григорій

@Greg, атрибут StringLength може задавати максимальну та мінімальну довжину.
Калеб Вір,

Що робити, якщо ви не хочете вказати максимальну довжину, а лише мінімальну? Ви запропонували здебільшого функціональне рішення, але воно не вирішує проблему з тим, що атрибут перевірки не перевіряється належним чином.
Джеремі Головац,

6
@JeremyHolovacs, якщо ви не хочете вказувати максимум, ви просто вказуєте int.MaxValueмаксимальну довжину, а потім встановлюєте властивість MinLength на будь-яку мінімальну довжину, яка вам потрібна. Так що, ні, це не просто функціональне рішення. Це також працює на практиці.
Дарін Димитров,

36

Я просто використав фрагмент jquery для вирішення цієї проблеми.

$("input[data-val-length-max]").each(function (index, element) {
   var length = parseInt($(this).attr("data-val-length-max"));
   $(this).prop("maxlength", length);
});

Селектор знаходить усі елементи, для яких встановлено атрибут data-val-length-max. Це атрибут, який встановить атрибут перевірки StringLength.

Кожен цикл перебирає ці збіги і аналізує значення цього атрибута та призначає його властивості mxlength, яку слід було встановити.

Просто додайте це до своєї функції готовності до документа, і все готово.


Це досить гладко.
TheOptimusPrimus

4
Ви можете використовувати .data ("val-length-max") замість .attr ("data-val-length-max") :)
hatsrumandcode


8

У MVC 4 Якщо вам потрібна максимальна довжина тексту типу введення? Ти можеш !

@Html.TextBoxFor(model => model.Item3.ADR_ZIP, new { @class = "gui-input ui-oblig", @maxlength = "5" })

4

Реквізит @ Nick-Harrison за його відповідь:

$("input[data-val-length-max]").each(function (index, element) {
var length = parseInt($(this).attr("data-val-length-max"));
$(this).prop("maxlength", length);
});

Мені було цікаво, для чого там parseInt ()? Я спростив це до цього без проблем ...

$("input[data-val-length-max]").each(function (index, element) {
    element.setAttribute("maxlength", element.getAttribute("data-val-length-max"))
});

Я б прокоментував відповідь Nicks, але ще не маю достатньо представників.


3

У мене була така сама проблема, і я зміг її вирішити, застосувавши інтерфейс IValidatableObject у моїй моделі перегляду.

public class RegisterViewModel : IValidatableObject
{
    /// <summary>
    /// Error message for Minimum password
    /// </summary>
    public static string PasswordLengthErrorMessage => $"The password must be at least {PasswordMinimumLength} characters";

    /// <summary>
    /// Minimum acceptable password length
    /// </summary>
    public const int PasswordMinimumLength = 8;

    /// <summary>
    /// Gets or sets the password provided by the user.
    /// </summary>
    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    /// <summary>
    /// Only need to validate the minimum length
    /// </summary>
    /// <param name="validationContext">ValidationContext, ignored</param>
    /// <returns>List of validation errors</returns>
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        var errorList = new List<ValidationResult>();
        if ((Password?.Length ?? 0 ) < PasswordMinimumLength)
        {
            errorList.Add(new ValidationResult(PasswordLengthErrorMessage, new List<string>() {"Password"}));
        }
        return errorList;
    }
}

Тоді розмітка в Бритві ...

<div class="form-group">
    @Html.LabelFor(m => m.Password)
    @Html.PasswordFor(m => m.Password, new { @class = "form-control input-lg" }
    <div class="password-helper">Must contain: 8 characters, 1 upper-case, 1 lower-case
    </div>
    @Html.ValidationMessagesFor(m => m.Password, new { @class = "text-danger" })
</div>

Це працює дуже добре. Якщо я спробую використати [StringLength] замість цього, відображений HTML просто неправильний. Перевірка повинна відображатись як:

<span class="text-danger field-validation-invalid field-validation-error" data-valmsg-for="Password" data-valmsg-replace="true"><span id="Password-error" class="">The Password should be a minimum of 8 characters long.</span></span>

За допомогою StringLengthAttribute відображений HTML відображається як ValidationSummary, що є неправильним. Найцікавіше, що коли валідатор не вдається, подання все одно блокується!


2

StringLength чудово працює, я використав це таким чином:

[StringLength(25,MinimumLength=1,ErrorMessage="Sorry only 25 characters allowed for 
              ProductName")]
public string ProductName { get; set; }

або просто використовувати RegularExpressionбез StringLength:

[RegularExpression(@"^[a-zA-Z0-9'@&#.\s]{1,25}$", ErrorMessage = "Reg Says Sorry only 25 
                   characters allowed for ProductName")]    
public string ProductName { get; set; }

але для мене вищезазначені методи привели до помилки в режимі відображення, оскільки я вже мав поле ProductName у базі даних, яке мало більше 25 символів

отже, нарешті, я натрапив на цей і цей пост і спробував перевірити без такої моделі :

 <div class="editor-field">
 @Html.TextBoxFor(model => model.ProductName, new
 {
 @class = "form-control",
 data_val = "true",
 data_val_length = "Sorry only 25 characters allowed for ProductName",
 data_val_length_max = "25",
 data_val_length_min = "1"
 })
 <span class="validation"> @Html.ValidationMessageFor(model => model.ProductName)</span>
 </div>

це вирішило мою проблему, ви також можете виконати перевірку вручну за допомогою jquery або за допомогою ModelState.AddModelError

надія комусь допомагає.


2

Я знаю, що я дуже спізнився на вечірку, але остаточно дізнався, як ми можемо зареєструвати MaxLengthAttribute.

Спочатку нам потрібен валідатор:

public class MaxLengthClientValidator : DataAnnotationsModelValidator<MaxLengthAttribute>
{
    private readonly string _errorMessage;
    private readonly int _length;


    public MaxLengthClientValidator(ModelMetadata metadata, ControllerContext context, MaxLengthAttribute attribute)
    : base(metadata, context, attribute)
    {
        _errorMessage = attribute.FormatErrorMessage(metadata.DisplayName);
        _length = attribute.Length;
    }

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = _errorMessage,
            ValidationType = "length"
        };

        rule.ValidationParameters["max"] = _length;
        yield return rule;
    }
}

Нічого справді особливого. У конструкторі ми зберігаємо деякі значення з атрибута. У GetClientValidationRulesми встановлюємо правило. ValidationType = "length"відображається data-val-lengthв рамках. rule.ValidationParameters["max"]для data-val-length-maxатрибута.

Тепер, оскільки у вас є валідатор, вам потрібно лише зареєструвати його в global.asax:

protected void Application_Start()
{
    //...

    //Register Validator
    DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(MaxLengthAttribute), typeof(MaxLengthClientValidator));
}

Et voila, це просто працює.


1

Я спробував це для всіх входів у моєму html-документі (textarea, inputs тощо), які мали властивість data-val-length-max, і воно працює коректно.

$(document).ready(function () {
    $(":input[data-val-length-max]").each(function (index, element) {
        var length = parseInt($(this).attr("data-val-length-max"));
        $(this).prop("maxlength", length);
    });
});

0

Це може замінити MaxLength і MinLength

[StringLength(40, MinimumLength = 10 , ErrorMessage = "Name cannot be longer than 40 characters and less than 10")]

0
<input class="text-box single-line" data-val="true" data-val-required="Name is required." 
    id="Name1" name="Name" type="text" value="">

$('#Name1').keypress(function () {
    if (this.value.length >= 5) return false;
});

6
Будь ласка, додайте опис
King Stone
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.