使用fluentvalidation和asp.net mvc的LessThanOrEqualTo不费一枪不显眼的客户端验证 [英] unobtrusive client validation using fluentvalidation and asp.net mvc LessThanOrEqualTo not firing

查看:114
本文介绍了使用fluentvalidation和asp.net mvc的LessThanOrEqualTo不费一枪不显眼的客户端验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下规则

使用不显眼,客户端验证一日不工作,二不

任何想法,为什么?

  RuleFor(X => x.StartDate)
    .LessThanOrEqualTo(X => x.EndDate.Value)
    .WithLocalizedMessage(()=> CommonRes.Less_Than_Or_Equal_To,过滤器= GT; CommonRes.Start_Date,过滤器= GT; CommonRes.End_Date);RuleFor(X => x.StartDate)
    .GreaterThanOrEqualTo(X => x.AbsoluteStartDate)
    .LessThanOrEqualTo(X => x.AbsoluteEndDate)
    .WithLocalizedMessage(()=> CommonRes.Between,过滤器= GT; CommonRes.Start_Date,过滤器= GT; filters.AbsoluteStartDate,过滤器= GT; filters.AbsoluteEndDate);


解决方案

既不的 LessThanOrEqualTo GreaterThanOrEqualTo 规则通过客户端验证作为<一个解释都支持href=\"http://fluentvalidation.$c$cplex.com/wikipage?title=mvc&referringTitle=Documentation\">documentation.

这意味着,如果你想对他们客户端验证,你需要编写一个自定义 FluentValidationPropertyValidator 和实施 GetClientValidationRules 方法,将允许您注册一个自定义的适配器和实施客户端验证逻辑,它在JavaScript。

如果您有兴趣如何,这可能只是实现ping通我,我会提供一个例子。


更新:

由于要求,我会尽量表现出一个如何实现对 LessThanOrEqualTo 规则定制客户端验证的例子。只有与非空的日期的特殊情况。写这样的定制客户端验证器对所有可能的情况下,当然是可能的,但它需要显著更多的努力。

所以我们先从视图模型和相应的验证:

  [验证(typeof运算(MyViewModelValidator))]
公共类MyViewModel
{
    [显示(NAME =开始日期)]
    [DisplayFormat(DataFormatString ={0:YYYY-MM-DD},ApplyFormatInEditMode = TRUE)]
    公开日期时间起始日期{搞定;组; }    公众的DateTime DateToCompareAgainst {搞定;组; }
}公共类MyViewModelValidator:AbstractValidator&LT; MyViewModel&GT;
{
    公共MyViewModelValidator()
    {
        RuleFor(X =&GT; x.StartDate)
            .LessThanOrEqualTo(X =&GT; x.DateToCompareAgainst)
            .WithMessage(无效的开始日期);
    }
}

然后,控制器:

 公共类HomeController的:控制器
{
    公众的ActionResult指数()
    {
        VAR模型=新MyViewModel
        {
            起始日期= DateTime.Now.AddDays(2),
            DateToCompareAgainst = DateTime.Now
        };
        返回查看(模型);
    }    [HttpPost]
    公众的ActionResult指数(MyViewModel模型)
    {
        返回查看(模型);
    }
}

和一个视图:

  @model MyViewModel
@using(Html.BeginForm())
{
    @ Html.Hidden(DateToCompareAgainst,Model.DateToCompareAgainst.ToString(YYYY-MM-DD))    @ Html.LabelFor(X =&GT; x.StartDate)
    @ Html.EditorFor(X =&GT; x.StartDate)
    @ Html.ValidationMessageFor(X =&GT; x.StartDate)
    &LT;按钮式=提交&GT;确定&LT; /按钮&GT;
}

这一切都是标准的东西为止。它将工作,但没有客户端验证。

第一步是写在 FluentValidationPropertyValidator

 公共类LessThanOrEqualToFluentValidationPropertyValidator:FluentValidationPropertyValidator
{
    公共LessThanOrEqualToFluentValidationPropertyValidator(ModelMetadata元,ControllerContext controllerContext,PropertyRule规则,IPropertyValidator验证)
        :基地(元数据,controllerContext,规则,验证)
    {
    }    公共覆盖的IEnumerable&LT; ModelClientValidationRule&GT; GetClientValidationRules()
    {
        如果(!this.ShouldGenerateClientSideRules())
        {
            产生中断;
        }        VAR验证=验证为LessThanOrEqualValidator;        VAR的errorMessage =新MessageFormatter()
            .AppendPropertyName(this.Rule.GetDisplayName())
            .BuildMessage(validator.ErrorMessageSource.GetString());        VAR规则=新ModelClientValidationRule
        {
            的ErrorMessage =的errorMessage,
            ValidationType =lessthanorequaldate
        };
        rule.ValidationParameters [其他] = CompareAttribute.FormatPropertyForClientValidation(validator.MemberToCompare.Name);
        产生回报规则;
    }
}

配置我们FluentValidation提供商时

将在的Application_Start 注册:

  FluentValidationModelValidatorProvider.Configure(X =&GT;
{
    x.Add(typeof运算(LessThanOrEqualValidator),(元数据,内容,规则,验证)=&gt;新建LessThanOrEqualToFluentValidationPropertyValidator(元数据,内容,规则,验证));
});

和的最后一个比特是在客户端上的自定义适配器。因此,我们在2脚本添加,当然我们的页面,以使不显眼的客户端验证:

 &LT;脚本的src =@ Url.Content(〜/脚本/ jquery.validate.js)TYPE =文/ JavaScript的&GT;&LT; / SCRIPT&GT;
&LT;脚本的src =@ Url.Content(〜/脚本/ jquery.validate.unobtrusive.js)TYPE =文/ JavaScript的&GT;&LT; / SCRIPT&GT;

和自定​​义适配器:

 (函数($){
    $ .validator.unobtrusive.adapters.add('lessthanorequaldate',['其他'],功能(选件){
        VAR getModel preFIX =函数(字段名){
            返回fieldName.substr(0,fieldName.lastIndexOf()+1。);
        };        VAR appendModel preFIX =功能(价值preFIX){
            如果(value.indexOf(*)=== 0){
                值= value.replace(*。,preFIX);
            }
            返回值;
        }        VAR preFIX = getModel preFIX(options.element.name)
            其他= options.params.other,
            fullOtherName = appendModel preFIX(其他,preFIX)
            元素= $(options.form).find(:输入[名称=+ fullOtherName +])[0];        options.rules ['lessthanorequaldate'] =元素;
        如果(options.message!= NULL){
            options.messages ['lessthanorequaldate'] = options.message;
        }
    });    $ .validator.addMethod('lessthanorequaldate',功能(价值元素,则params){
        VAR parseDate =功能(日期){
            变种M = date.match(/ ^(\\ d {4}) - (\\ d {1,2}) - (\\ d {1,2})$ /);
            返回M'新的日期(parseInt函数(M [1]),parseInt函数(M [2]) - 1,parseInt函数(M [3])):空;
        };        VAR日期= parseDate(值);
        变种dateToCompareAgainst = parseDate($(PARAMS).VAL());        如果(isNaN(date.getTime())|| isNaN(dateToCompareAgainst.getTime())){
            返回false;
        }        归期&LT; = dateToCompareAgainst;
    });})(jQuery的);

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.

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.

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. 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:

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:

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:

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

这篇关于使用fluentvalidation和asp.net mvc的LessThanOrEqualTo不费一枪不显眼的客户端验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆