validation client discrète utilisant fluentvalidation et asp.net mvc LessThanOrEqualTo ne pas déclencher

J’ai les règles suivantes

le premier fonctionne avec une validation côté client discrète, le second ne fonctionne pas

des idées pourquoi?

RuleFor(x => x.StartDate) .LessThanOrEqualTo(x => x.EndDate.Value) .WithLocalizedMessage(() => CommonRes.Less_Than_Or_Equal_To, filters => CommonRes.Start_Date, filters => CommonRes.End_Date); RuleFor(x => x.StartDate) .GreaterThanOrEqualTo(x => x.AbsoluteStartDate) .LessThanOrEqualTo(x => x.AbsoluteEndDate) .WithLocalizedMessage(() => CommonRes.Between, filters => CommonRes.Start_Date, filters => filters.AbsoluteStartDate, filters => filters.AbsoluteEndDate); 

Aucune des règles LessThanOrEqualTo ou GreaterThanOrEqualTo n’est prise en charge par la validation côté client, comme expliqué dans la documentation .

Cela signifie que si vous voulez les valider côté client, vous devrez écrire un FluentValidationPropertyValidator personnalisé et implémenter la méthode GetClientValidationRules qui vous permettra d’enregistrer un adaptateur personnalisé et d’implémenter la logique de validation côté client en javascript.

Si vous êtes intéressé par la façon dont cela pourrait être réalisé, faites un ping et je vous donnerai un exemple.


Mettre à jour

En tant que demande, je vais essayer de montrer un exemple de la façon dont on pourrait implémenter la validation côté client personnalisée pour la règle LessThanOrEqualTo . Ce n’est qu’un cas particulier avec des dates non nullables. Il est bien sûr possible d’écrire un validateur côté client personnalisé pour tous les cas possibles, mais cela demandera beaucoup plus d’efforts.

Nous commençons donc avec un modèle de vue et un validateur correspondant:

 [Validator(typeof(MyViewModelValidator))] public class MyViewModel { [Display(Name = "Start date")] [DisplayFormat(DataFormatSsortingng = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] public DateTime StartDate { get; set; } public DateTime DateToCompareAgainst { get; set; } } public class MyViewModelValidator : AbstractValidator { public MyViewModelValidator() { RuleFor(x => x.StartDate) .LessThanOrEqualTo(x => x.DateToCompareAgainst) .WithMessage("Invalid start date"); } } 

Puis un contrôleur:

 public class HomeController : Controller { public ActionResult Index() { var model = new MyViewModel { StartDate = DateTime.Now.AddDays(2), DateToCompareAgainst = DateTime.Now }; return View(model); } [HttpPost] public ActionResult Index(MyViewModel model) { return View(model); } } 

et une vue:

 @model MyViewModel @using (Html.BeginForm()) { @Html.Hidden("DateToCompareAgainst", Model.DateToCompareAgainst.ToSsortingng("yyyy-MM-dd")) @Html.LabelFor(x => x.StartDate) @Html.EditorFor(x => x.StartDate) @Html.ValidationMessageFor(x => x.StartDate)  } 

Tout cela est la norme jusqu’ici. Cela fonctionnera mais sans validation du client.

La première étape consiste à écrire le FluentValidationPropertyValidator :

 public class LessThanOrEqualToFluentValidationPropertyValidator : FluentValidationPropertyValidator { public LessThanOrEqualToFluentValidationPropertyValidator(ModelMetadata metadata, ControllerContext controllerContext, PropertyRule rule, IPropertyValidator validator) : base(metadata, controllerContext, rule, validator) { } public override IEnumerable GetClientValidationRules() { if (!this.ShouldGenerateClientSideRules()) { yield break; } var validator = Validator as LessThanOrEqualValidator; var errorMessage = new MessageFormatter() .AppendPropertyName(this.Rule.GetDisplayName()) .BuildMessage(validator.ErrorMessageSource.GetSsortingng()); var rule = new ModelClientValidationRule { ErrorMessage = errorMessage, ValidationType = "lessthanorequaldate" }; rule.ValidationParameters["other"] = CompareAtsortingbute.FormatPropertyForClientValidation(validator.MemberToCompare.Name); yield return rule; } } 

qui sera enregistré dans Application_Start lors de la configuration de notre fournisseur FluentValidation:

 FluentValidationModelValidatorProvider.Configure(x => { x.Add(typeof(LessThanOrEqualValidator), (metadata, context, rule, validator) => new LessThanOrEqualToFluentValidationPropertyValidator(metadata, context, rule, validator)); }); 

Et le dernier bit est l’adaptateur personnalisé sur le client. Nous ajoutons donc bien sûr les 2 scripts à notre page pour permettre une validation côté client discrète:

   

et l’adaptateur personnalisé:

 (function ($) { $.validator.unobtrusive.adapters.add('lessthanorequaldate', ['other'], function (options) { var getModelPrefix = function (fieldName) { return fieldName.substr(0, fieldName.lastIndexOf(".") + 1); }; var appendModelPrefix = function (value, prefix) { if (value.indexOf("*.") === 0) { value = value.replace("*.", prefix); } return value; } var prefix = getModelPrefix(options.element.name), other = options.params.other, fullOtherName = appendModelPrefix(other, prefix), element = $(options.form).find(":input[name=" + fullOtherName + "]")[0]; options.rules['lessthanorequaldate'] = element; if (options.message != null) { options.messages['lessthanorequaldate'] = options.message; } }); $.validator.addMethod('lessthanorequaldate', function (value, element, params) { var parseDate = function (date) { var m = date.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/); return m ? new Date(parseInt(m[1]), parseInt(m[2]) - 1, parseInt(m[3])) : null; }; var date = parseDate(value); var dateToCompareAgainst = parseDate($(params).val()); if (isNaN(date.getTime()) || isNaN(dateToCompareAgainst.getTime())) { return false; } return date <= dateToCompareAgainst; }); })(jQuery); 

L’exemple de Darin contient des éléments obsolètes, alors voici un exemple plus à jour que j’ai qui fait des comparaisons de numéros. Vous pouvez facilement le modifier pour les comparaisons de dates si:

Javascript:

 (function ($) { $.validator.addMethod("lessthanorequal", function(value, element, param) { return this.optional(element) || parseFloat(value) <= parseFloat(param); }, "Must be less than"); $.validator.unobtrusive.adapters.add("lessthanorequal", ["field"], function (options) { options.rules["lessthanorequal"] = options.params.field; if (options.message) options.messages["lessthanorequal"] = options.message; }); })(jQuery); 

C #

 public class LessThanOrEqualPropertyValidator : FluentValidationPropertyValidator { public LessThanOrEqualPropertyValidator(ModelMetadata metadata, ControllerContext controllerContext, PropertyRule rule, IPropertyValidator validator) : base(metadata, controllerContext, rule, validator) { } public override IEnumerable GetClientValidationRules() { if (!ShouldGenerateClientSideRules()) yield break; var formatter = new MessageFormatter().AppendPropertyName(Rule.PropertyName); ssortingng message = formatter.BuildMessage(Validator.ErrorMessageSource.GetSsortingng()); var rule = new ModelClientValidationRule { ValidationType = "lessthanorequal", ErrorMessage = message }; rule.ValidationParameters["field"] = ((LessThanOrEqualValidator)Validator).ValueToCompare; yield return rule; } } 

Global.asax Application_Start:

 FluentValidation.Mvc.FluentValidationModelValidatorProvider.Configure(x => { x.Add(typeof(LessThanOrEqualValidator), (metadata, context, description, validator) => new LessThanOrEqualPropertyValidator(metadata, context, description, validator)); }); 

Donc, maintenant, toute règle numérique utilisant LessThanOrEqual sera validée côté client.

LessThanOrEqualTo et GreaterThanOrEqualTo ne prennent pas en charge la validation client hors de la boîte.

Cependant, InclusiveBetween est pris en charge. Donc, vous pouvez utiliser InclusiveBetween .

Exemple

 RuleFor(x => x.StartDate) .InclusiveBetween(x.AbsoluteStartDate, x.AbsoluteEndDate) 

Voir la documentation pour plus d’informations sur les méthodes client supscopes .