簡體   English   中英

使用fluentvalidation和asp.net mvc LessThanOrEqualTo不觸發的不顯眼的客戶端驗證

[英]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);

客戶端驗證不支持LessThanOrEqualToGreaterThanOrEqualTo規則,如文檔中所述。

這意味着如果您希望對它們進行客戶端驗證,則需要編寫自定義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的數字規則都將被驗證客戶端。

LessThanOrEqualToGreaterThanOrEqualTo不支持開箱即用的客戶端驗證。

但是,支持InclusiveBetween 所以你可以使用InclusiveBetween

RuleFor(x => x.StartDate)
    .InclusiveBetween(x.AbsoluteStartDate, x.AbsoluteEndDate)

有關支持的客戶端方法的信息,請參閱文檔。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM