MaxLength属性不生成客户端验证属性

时间:2011-07-23 16:10:23

标签: c# asp.net-mvc validation asp.net-mvc-3 model-validation

我对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的迹象,但其他一切似乎都在起作用。

任何想法出了什么问题?

10 个答案:

答案 0 :(得分:138)

尝试使用[StringLength]属性:

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

这是用于验证的目的。如果要在输入上设置例如maxlength属性,可以将自定义数据注释元数据提供程序编写为shown in this post并自定义default templates

答案 1 :(得分: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属性。

只需将此添加到您的文档就绪功能中,您就可以了。

答案 2 :(得分:8)

自MVC 5.1更新后,

MaxLengthAttribute正在运行:change notes

答案 3 :(得分:6)

在MVC 4中 如果你想在输入类型文本中使用maxlenght?您可以 !

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

答案 4 :(得分: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"))
});

我会评论尼克斯的答案,但还没有足够的代表。

答案 5 :(得分:3)

I had this same problem and I was able to solve it by implementing the IValidatableObject interface in my view model.

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;
    }
}

The markup in the Razor is then...

<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>

This works really well. If I attempt to use [StringLength] instead then the rendered HTML is just not correct. The validation should render as:

<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>

With the StringLengthAttribute the rendered HTML shows as a ValidationSummary which is not correct. The funny thing is that when the validator fails the submit is still blocked!

答案 6 :(得分:1)

我知道我参加派对的时间已经很晚了,但我最终发现了如何注册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-lengthrule.ValidationParameters["max"]适用于data-val-length-max属性。

既然你有一个验证器,你只需要在global.asax注册它:

protected void Application_Start()
{
    //...

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

呃瞧,它只是有效。

答案 7 :(得分:1)

我为我的html文档(textarea,输入等)中的所有输入尝试了这个,这些输入具有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);
    });
});

答案 8 :(得分:0)

这可以取代MaxLength和MinLength

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

答案 9 :(得分: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;
});