Asp.net-Mvc-3

使用 FluentValidation/MVC 3 驗證客戶端上的複選框

  • September 27, 2016

我正在嘗試驗證是否使用 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>

引用自:https://stackoverflow.com/questions/9808794