[英]unobtrusive client validation using fluentvalidation and asp.net mvc LessThanOrEqualTo not firing
I have the following rules 我有以下规则
the 1st does work using unobtrusive, client side validation, the second does not 第一个使用不显眼的客户端验证工作,第二个没有
any ideas why? 任何想法为什么?
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);
Neither of the LessThanOrEqualTo
or GreaterThanOrEqualTo
rules are supported by client side validation as explained in the documentation . 客户端验证不支持
LessThanOrEqualTo
或GreaterThanOrEqualTo
规则,如文档中所述。
This means that if you want to have client side validation for them you will need to write a custom FluentValidationPropertyValidator
and implement the GetClientValidationRules
method which will allow you to register a custom adapter and implement the client side validation logic for it in javascript. 这意味着如果您希望对它们进行客户端验证,则需要编写自定义
FluentValidationPropertyValidator
并实现GetClientValidationRules
方法, GetClientValidationRules
方法允许您注册自定义适配器并在javascript中为其实现客户端验证逻辑。
If you are interested on how this could be achieved just ping me and I will provide an example. 如果您对如何实现这一点感兴趣,请点击我,我将提供一个示例。
Update 更新
As request, I will try to show an example of how one could implement custom client side validation for the LessThanOrEqualTo
rule. 作为请求,我将尝试展示如何为
LessThanOrEqualTo
规则实现自定义客户端验证的示例。 It is only a particular case with non-nullable dates. 这只是一个具有非可空日期的特殊情况。 Writing such custom client side validator for all the possible case is of course possible but it will require significantly more efforts.
为所有可能的情况编写这样的自定义客户端验证器当然是可能的,但需要更多的努力。
So we start with a view model and a corresponding validator: 所以我们从视图模型和相应的验证器开始:
[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");
}
}
Then a controller: 然后一个控制器:
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);
}
}
and a view: 和一个观点:
@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>
}
All this is standard stuff so far. 到目前为止,这一切都是标准的。 It will work but without client validation.
它可以工作但没有客户端验证。
The first step is to write the FluentValidationPropertyValidator
: 第一步是编写
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;
}
}
which will be registered in Application_Start
when configuring our FluentValidation provider: 在配置我们的FluentValidation提供
Application_Start
时将在Application_Start
中注册:
FluentValidationModelValidatorProvider.Configure(x =>
{
x.Add(typeof(LessThanOrEqualValidator), (metadata, context, rule, validator) => new LessThanOrEqualToFluentValidationPropertyValidator(metadata, context, rule, validator));
});
And the last bit is the custom adapter on the client. 最后一点是客户端上的自定义适配器。 So we add of course the 2 scripts to our page in order to enable unobtrusive client side validation:
因此,我们在页面中添加了2个脚本,以便实现不显眼的客户端验证:
<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>
and the custom adapter: 和自定义适配器:
(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);
Darin's example has some obsolete stuff in it, so here is a more updated example that I have that does number comparisons. Darin的例子中有一些过时的东西,所以这里有一个更新的例子,我有数字比较。 You can easily tweak it for date comparisons though:
您可以轻松调整它以进行日期比较:
Javascript: 使用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# 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: Global.asax Application_Start:
FluentValidation.Mvc.FluentValidationModelValidatorProvider.Configure(x =>
{
x.Add(typeof(LessThanOrEqualValidator), (metadata, context, description, validator) => new LessThanOrEqualPropertyValidator(metadata, context, description, validator));
});
So now any number rule that uses LessThanOrEqual will be validated client side. 所以现在任何使用LessThanOrEqual的数字规则都将被验证客户端。
LessThanOrEqualTo
and GreaterThanOrEqualTo
do not support clientside validation out of the box. LessThanOrEqualTo
和GreaterThanOrEqualTo
不支持开箱即用的客户端验证。
However, InclusiveBetween
is supported. 但是,支持
InclusiveBetween
。 So you could use InclusiveBetween
. 所以你可以使用
InclusiveBetween
。
Example 例
RuleFor(x => x.StartDate)
.InclusiveBetween(x.AbsoluteStartDate, x.AbsoluteEndDate)
See the documentation for mor information about supported clientside methods . 有关支持的客户端方法的信息,请参阅文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.