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?
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 .
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.
MaxLengthAttribute
fonctionne depuis la mise à jour MVC 5.1: notes de modification
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.
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é!
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.
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);
});
});
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.
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")]
<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;
});