Asp.net-Mvc-3
使用 FluentValidation/MVC 3 驗證客戶端上的複選框
我正在嘗試驗證是否使用 FluentValidation 在客戶端上選中了一個複選框。我一輩子都想不通。
可以使用不顯眼的驗證來完成嗎?
假設您有以下模型:
[Validator(typeof(MyViewModelValidator))] public class MyViewModel { public bool IsChecked { get; set; } }使用以下驗證器:
public class MyViewModelValidator : AbstractValidator<MyViewModel> { public MyViewModelValidator() { RuleFor(x => x.IsChecked).Equal(true).WithMessage("Please check this checkbox"); } }和一個控制器:
public class HomeController : Controller { public ActionResult Index() { return View(); } [HttpPost] public ActionResult Index(MyViewModel model) { return View(model); } }帶有相應的視圖:
@model MyViewModel @using (Html.BeginForm()) { @Html.LabelFor(x => x.IsChecked) @Html.CheckBoxFor(x => x.IsChecked) @Html.ValidationMessageFor(x => x.IsChecked) <button type="submit">OK</button> }並且
Global.asax您已經註冊了流利的驗證模型驗證器提供程序:FluentValidationModelValidatorProvider.Configure();到目前為止,我們已經啟動並執行了伺服器端驗證。那挺好的。這始終是我們必須設置的第一部分。我見過人們過於關注客戶端驗證,以至於他們忘記了伺服器端驗證,當你禁用 javascript(或者如果你偶然發現一個懷有惡意的使用者時更糟),那麼糟糕的事情就會發生。到目前為止,我們很有信心,因為我們知道即使客戶端出現問題,我們的域也會受到伺服器端驗證的保護。
所以現在讓我們來處理客戶端驗證。開箱即用的 FluentValidation.NET 支持驗證器的自動客戶端驗證,
EqualTo但在與另一個屬性值進行比較時,它相當於[Compare]數據註釋。但在我們的例子中,我們正在與一個固定值進行比較。所以我們沒有開箱即用的客戶端驗證。當我們沒有從盒子裡拿出東西時,我們需要把它放進盒子裡。
所以我們首先定義一個自定義的 FluentValidationPropertyValidator:
public class EqualToValueFluentValidationPropertyValidator : FluentValidationPropertyValidator { public EqualToValueFluentValidationPropertyValidator(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 = (EqualValidator)Validator; var errorMessage = new MessageFormatter() .AppendPropertyName(Rule.GetDisplayName()) .AppendArgument("ValueToCompare", validator.ValueToCompare) .BuildMessage(validator.ErrorMessageSource.GetString()); var rule = new ModelClientValidationRule(); rule.ErrorMessage = errorMessage; rule.ValidationType = "equaltovalue"; rule.ValidationParameters["valuetocompare"] = validator.ValueToCompare; yield return rule; } }我們要註冊
Application_Start:FluentValidationModelValidatorProvider.Configure(provider => { provider.AddImplicitRequiredValidator = false; provider.Add(typeof(EqualValidator), (metadata, context, description, validator) => new EqualToValueFluentValidationPropertyValidator(metadata, context, description, validator)); });到目前為止,我們已經將自定義 FluentValidationPropertyValidator 與 EqualValidator 相關聯。
最後一部分是編寫自定義適配器:
(function ($) { $.validator.unobtrusive.adapters.add('equaltovalue', ['valuetocompare'], function (options) { options.rules['equaltovalue'] = options.params; if (options.message != null) { options.messages['equaltovalue'] = options.message; } }); $.validator.addMethod('equaltovalue', function (value, element, params) { if ($(element).is(':checkbox')) { if ($(element).is(':checked')) { return value.toLowerCase() === 'true'; } else { return value.toLowerCase() === 'false'; } } return params.valuetocompare.toLowerCase() === value.toLowerCase(); }); })(jQuery);差不多就是這樣。剩下的就是包含客戶端腳本:
<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> <script src="@Url.Content("~/Scripts/customadapter.js")" type="text/javascript"></script>