[英]unobtrusive client validation using fluentvalidation and asp.net mvc LessThanOrEqualTo not firing
我有以下規則
第一個使用不顯眼的客戶端驗證工作,第二個沒有
任何想法為什么?
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);
客戶端驗證不支持LessThanOrEqualTo
或GreaterThanOrEqualTo
規則,如文檔中所述。
這意味着如果您希望對它們進行客戶端驗證,則需要編寫自定義FluentValidationPropertyValidator
並實現GetClientValidationRules
方法, GetClientValidationRules
方法允許您注冊自定義適配器並在javascript中為其實現客戶端驗證邏輯。
如果您對如何實現這一點感興趣,請點擊我,我將提供一個示例。
更新
作為請求,我將嘗試展示如何為LessThanOrEqualTo
規則實現自定義客戶端驗證的示例。 這只是一個具有非可空日期的特殊情況。 為所有可能的情況編寫這樣的自定義客戶端驗證器當然是可能的,但需要更多的努力。
所以我們從視圖模型和相應的驗證器開始:
[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>
}
到目前為止,這一切都是標准的。 它可以工作但沒有客戶端驗證。
第一步是編寫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;
}
}
在配置我們的FluentValidation提供Application_Start
時將在Application_Start
中注冊:
FluentValidationModelValidatorProvider.Configure(x =>
{
x.Add(typeof(LessThanOrEqualValidator), (metadata, context, rule, validator) => new LessThanOrEqualToFluentValidationPropertyValidator(metadata, context, rule, validator));
});
最后一點是客戶端上的自定義適配器。 因此,我們在頁面中添加了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>
和自定義適配器:
(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的例子中有一些過時的東西,所以這里有一個更新的例子,我有數字比較。 您可以輕松調整它以進行日期比較:
使用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的數字規則都將被驗證客戶端。
LessThanOrEqualTo
和GreaterThanOrEqualTo
不支持開箱即用的客戶端驗證。
但是,支持InclusiveBetween
。 所以你可以使用InclusiveBetween
。
例
RuleFor(x => x.StartDate)
.InclusiveBetween(x.AbsoluteStartDate, x.AbsoluteEndDate)
有關支持的客戶端方法的信息,請參閱文檔。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.