87 votes

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

J'ai un curieux problème avec la validation côté client d'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 HTML généré que j'obtiens 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 la MaxLengthAttribute mais tout le reste semble fonctionner.

Une idée de ce qui ne va pas ?

3voto

ScottyMacDev Points 117

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

La majoration 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 très bien. Si j'essaie d'utiliser [StringLength] à la place, le HTML rendu n'est tout simplement pas correct. La validation devrait ê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 l'attribut StringLengthAttribute, le HTML rendu apparaît comme un ValidationSummary, ce qui n'est pas correct. Ce qui est amusant, c'est que lorsque le validateur échoue, l'envoi est toujours bloqué !

3voto

Je sais que je suis très en retard sur la fête, mais j'ai enfin trouvé comment on peut enregistrer l'image de marque de l'entreprise. MaxLengthAttribute .

Tout d'abord, nous avons 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 le constructeur GetClientValidationRules nous établissons une règle. ValidationType = "length" est mis en correspondance avec data-val-length par le cadre. rule.ValidationParameters["max"] est pour le data-val-length-max attribut.

Maintenant que vous disposez d'un validateur, il vous suffit de l'enregistrer dans la section global.asax :

protected void Application_Start()
{
    //...

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

Et voilà, ça marche.

2voto

stom Points 2477

StringLength ça marche très bien, je l'ai utilisé comme ça :

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

ou Utilisez simplement 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 la vue d'affichage, parce que j'avais déjà le champ ProductName dans la base de données qui avait plus de 25 caractères.

J'ai fini par tomber sur ce y ce post et a essayé de valider sans modèle comme ceci :

 <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 aussi faire la validation manuellement en utilisant jquery ou en utilisant ModelState.AddModelError (État du modèle)

J'espère que cela aidera quelqu'un.

1voto

J'ai essayé cela pour toutes les entrées de mon document html (textarea, inputs, etc) qui avaient la propriété data-val-length-max et cela fonctionne 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);
    });
});

0voto

amal50 Points 437

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")]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X