MaxLength属性がクライアント側の検証属性を生成しない


83

ASP.NETMVC3クライアント側の検証に奇妙な問題があります。私は次のクラスを持っています:

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 CodeFirstがStringLength属性によって課された最大長でDB列を作成することを確認しました。:)
マットジェンキンス

しかし、これは答えではありません。MinLength属性も機能しないため
Hryhorii 2011

@ Greg、StringLength属性は、最大長と最小長を指定できます。
Caleb Vear 2011

最大長を指定したくない場合はどうしますか?最小だけですか?ほとんど機能的な回避策を提案しましたが、検証属性が適切に検証されていないという問題には対処していません。
Jeremy Holovacs 2011年

6
@JeremyHolovacs、最大値を指定したくない場合は、単にint.MaxValue最大長として指定し、MinLengthプロパティを必要な最小長に設定します。したがって、いいえ、それは単なる機能的な回避策ではありません。それは実際にも機能するものです。
ダリンディミトロフ2011年

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 2013

4
.attr( "data-val-length-max")の代わりに.data( "val-length-max")を使用できます:)
hatsrumandcode 2016年


8

MVC 4の場合入力タイプのテキストにmaxlenghtが必要な場合は?あなたはできる !

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

またはRegularExpressionStringLengthなしで使用する:

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

しかし、上記のメソッドでは、表示ビューでエラーが発生しました。これは、データベースに25文字を超えるProductNameフィールドが既に存在するためです。

だからついに私はこれこの投稿に出くわし、このようなモデルなしで検証しようとしました:

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

出来上がり、それはうまくいきます。


1

data-val-length-maxプロパティを持つhtmlドキュメント(textarea、inputsなど)のすべての入力に対してこれを試しましたが、正しく機能します。

$(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
説明を追加してください
キングストーン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.