web-dev-qa-db-fra.com

L'attribut MaxLength ne génère pas d'attributs de validation côté client

J'ai un problème curieux avec la validation côté client ASP.NET MVC3. J'ai la classe suivante:

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

De mon point de vue:

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

Et voici le code HTML généré pour la zone de texte de ce champ:

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

Aucun signe de MaxLengthAttribute, mais tout le reste semble fonctionner.

Des idées sur ce qui ne va pas?

72
Matt Jenkins

Essayez d'utiliser l'attribut [StringLength]:

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

C'est à des fins de validation. Si vous souhaitez définir par exemple l'attribut maxlength sur l'entrée, vous pouvez écrire un fournisseur de métadonnées d'annotations de données personnalisé sous la forme indiqué dans cet article et personnaliser les modèles default .

136
Darin Dimitrov

Je viens d'utiliser un extrait de JQuery pour résoudre ce problème.

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

Le sélecteur recherche tous les éléments ayant un ensemble d'attributs data-val-length-max. C'est l'attribut que l'attribut de validation StringLength va définir.

Chaque boucle parcourt ces correspondances et analysera la valeur de cet attribut et l'affectera à la propriété mxlength qui aurait dû être définie.

Ajoutez simplement ceci à votre fonction de préparation de document et vous êtes prêt à partir.

35
Nick Harrison

MaxLengthAttribute fonctionne depuis la mise à jour MVC 5.1: notes de modification

8
Michael Logutov

Dans MVC 4 Si vous voulez maxlength dans le type de texte saisi? Vous pouvez ! 

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

Les accessoires à @ Nick-Harrison pour sa réponse:

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

Je me demandais à quoi servait parseInt ()? Je l'ai simplifié à cela sans aucun problème ...

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

J'aurais commenté la réponse de Nicks mais je n'ai pas encore assez de représentants.

4
EamonnM

J'ai eu ce même problème et j'ai pu le résoudre en implémentant l'interface IValidatableObject dans mon modèle de vue. 

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

Le balisage dans le rasoir est alors ...

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

Cela fonctionne vraiment bien. Si j'essaie d'utiliser [StringLength] à la place, le code HTML rendu n'est tout simplement pas correct. La validation doit être rendue comme suit:

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

Avec StringLengthAttribute, le code HTML affiché s’affiche sous la forme d’un ValidationSummary incorrect. Ce qui est amusant, c'est que lorsque le validateur échoue, l'envoi est toujours bloqué! 

3
ScottyMacDev

StringLength fonctionne très bien, je l'ai utilisé de cette façon:

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

ou Il suffit d'utiliser RegularExpression sans StringLength:

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

mais pour moi les méthodes ci-dessus ont donné une erreur dans l'affichage, parce que j'avais déjà le champ ProductName dans la base de données qui avait plus de 25 caractères

donc finalement je suis tombé sur this et this post et j'ai essayé de valider sans modèle comme celui-ci:

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

cela a résolu mon problème, vous pouvez également effectuer la validation manuellement à l’aide de jquery ou de ModelState.AddModelError

l'espoir aide quelqu'un.

2
stom

J'ai essayé cela pour toutes les entrées de mon document HTML (textarea, entrées, etc.) qui possédaient la propriété data-val-length-max et qui fonctionnait correctement.

$(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);
    });
});
1

Je sais que je suis très en retard à la fête, mais j’ai finalement découvert comment enregistrer la MaxLengthAttribute.

Nous avons d'abord besoin d'un validateur:

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

Rien de vraiment spécial. Dans le constructeur, nous sauvegardons certaines valeurs de l'attribut. Dans la GetClientValidationRules nous établissons une règle. ValidationType = "length" est associé à data-val-length par la structure. rule.ValidationParameters["max"] est pour l'attribut data-val-length-max.

Maintenant que vous avez un validateur, il vous suffit de l’inscrire dans global.asax:

protected void Application_Start()
{
    //...

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

Et voila, ça marche.

1

Cela peut remplacer la longueur maximale et la longueur minimale

[StringLength(40, MinimumLength = 10 , ErrorMessage = "Name cannot be longer than 40 characters and less than 10")]
0
amal50
<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;
});
0
Nithya