不显眼的客户端validation使用fluentvalidation和asp.net mvc LessThanOrEqualTo不发射

我有以下规则

第一个是使用不显眼的客户端validation工作,第二个不是

任何想法为什么?

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

如文档中所述,客户端validation不支持LessThanOrEqualToGreaterThanOrEqualTo规则。

这意味着如果你想为它们进行客户端validation,你将需要编写一个自定义的FluentValidationPropertyValidator并实现GetClientValidationRules方法, GetClientValidationRules方法将允许你注册一个自定义的适配器并在javascript中实现它的客户端validation逻辑。

如果你对如何实现这个目标感兴趣,那么我只能提供一个例子。


更新:

作为请求,我将尝试展示如何为LessThanOrEqualTo规则实现自定义客户端validation的示例。 这只是一个具有不可空date的特殊情况。 为所有可能的情况编写这样的自定义客户端validation器当然是可能的,但是这将需要更多的努力。

所以我们从视图模型和相应的validation器开始:

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

然后一个控制器:

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

和一个观点:

 @model MyViewModel @using (Html.BeginForm()) { @Html.Hidden("DateToCompareAgainst", Model.DateToCompareAgainst.ToString("yyyy-MM-dd")) @Html.LabelFor(x => x.StartDate) @Html.EditorFor(x => x.StartDate) @Html.ValidationMessageFor(x => x.StartDate) <button type="submit">OK</button> } 

所有这些都是标准的东西。 这将工作,但没有客户端validation。

第一步是编写FluentValidationPropertyValidator

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

在configuration我们的FluentValidation提供Application_Start时将在Application_Start中注册:

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

最后一位是客户端上的自定义适配器。 所以我们将2个脚本添加到我们的页面,以便实现不显眼的客户端validation:

 <script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script> 

和自定义适配器:

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

达林的例子有一些过时的东西,所以这里是一个更新的例子,我有那个数字比较。 你可以很容易地调整date比较:

使用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<ModelClientValidationRule> GetClientValidationRules() { if (!ShouldGenerateClientSideRules()) yield break; var formatter = new MessageFormatter().AppendPropertyName(Rule.PropertyName); string message = formatter.BuildMessage(Validator.ErrorMessageSource.GetString()); 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)); }); 

所以现在任何使用LessThanOrEqual的数字规则都将被validation客户端。