FluentValidation 谓词验证器不起作用

Posted

技术标签:

【中文标题】FluentValidation 谓词验证器不起作用【英文标题】:FluentValidation predicate validator doesn't work 【发布时间】:2014-07-01 13:18:53 【问题描述】:

我有模型课:

[FluentValidation.Attributes.Validator(typeof(CrcValidator))]
public class CrcModel

    [Display(Name = "Binary value")]
    public string binaryValue  get; set; 

    [Display(Name = "Generator")]
    public string generator  get; set; 

和带有谓词的验证器类:

public class CrcValidator : AbstractValidator<CrcModel>

    public CrcValidator()
    
        RuleFor(x => x.binaryValue)
            .NotEmpty().WithMessage("Binary value is required")
            .Matches(@"(0|1)*").WithMessage("This value is not valid binary value");

        RuleFor(x => x.generator)
            .NotEmpty().WithMessage("Generator is required")
            .Matches(@"(0|1)*").WithMessage("Generator must be valid binary value")
            .Must(CompareLength).WithMessage("Length must be lesser than length of binary value - 1");
    

    private bool CompareLength(CrcModel model, string value)
    
        return model.binaryValue.Length - 1 > model.generator.Length;
    

我在 CompareLength 函数中放置了断点,并且从表单中正确读取了每个值。问题是我的表单通过了验证,即使我的谓词函数返回 false。 NotEmpty 和 Matches 规则工作得很好,只有 Must 似乎被省略了。

编辑

提交按钮的jQuery(“按钮”类型):

$(function () 
$("#Button1").click(function () 
    var form = $("#Form1");
    if ($(form).valid()) 
        $.ajax(
            type: 'POST',
            url: 'Compute',
            data: $(form).serialize(),
            success: function (result) 
                $("#remainder").val(result.remainder);
                $("#signal").val(result.signal);
            
        );
    
); 
);

控制器动作处理表单提交:

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Compute([Bind(Include = "binaryValue,generator")] CrcModel model)
    
        if (ModelState.IsValid)
        
            model.remainder = ComputeFrame(model.binaryValue, model.generator);
            model.signal = model.binaryValue + model.remainder;
        

        return Json(new  remainder = model.remainder, signal = model.signal );
    

来自 Must 规则的验证在服务器端有效,但消息不显示。

【问题讨论】:

【参考方案1】:

编辑:在几个 cmets 之后,在 FluentValidation 中对 Must 的所有调用中定义的验证仅在服务器上执行。没有与任意 C# 代码等效的 javascript。 C# 中的 FluentValidation 规则由 MVC 框架转换为 html 中表单字段标签上的各种 HTML5 data-* 属性,jQuery Validate 在客户端验证期间读取这些属性。由于无法将谓词(委托方法)中定义的验证规则转换为 HTML5 data-* 属性,因此这些验证规则只能在服务器端强制执行。

编辑 #2: 看到 Must 验证是由 AJAX 调用触发的,您需要做几件事:

    将 HTTP 状态代码设置为非 200 响应以触发 jQuery 中的错误处理机制。另外,将 HTTP 状态设置为 422(无法处理的实体)

    HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Compute([Bind(Include = "binaryValue,generator")] CrcModel model)
    
        if (ModelState.IsValid)
        
            model.remainder = ComputeFrame(model.binaryValue, model.generator);
            model.signal = model.binaryValue + model.remainder;
    
            return Json(new  remainder = model.remainder, signal = model.signal );
        
        else
        
            Response.StatusCode = 422;
    
            return Json(new  errors = ModelState.Errors );
        
    
    

    更改 jQuery.ajax 调用:

    $(function () 
        $("#Button1").click(function () 
            var form = $("#Form1");
            if ($(form).valid()) 
                $.ajax(
                    type: 'POST',
                    url: 'Compute',
                    data: $(form).serialize(),
                    success: function (result) 
                        $("#remainder").val(result.remainder);
                        $("#signal").val(result.signal);
                    ,
                    error: function(xhr) 
                        if (xhr.status == 422) 
                            var errors = JSON.parse(xhr.responseText);
    
                            console.log(errors);
                        
                    
                );
            
        ); 
    );
    

另一种方法是只渲染一个将一个或多个错误消息显示为 HTML 的 Partial,然后将该 HTML 设置在 DIV 中并显示 DIV 标记。

【讨论】:

嗯。奇怪的。我已经在 ASP.NET MVC 4 中使用过这种东西,它工作正常。所以ModelState.IsValid 报告true 哦,亲爱的,实际上我忘记在控制器中检查 ModelState.IsValid 并且我认为如果给定的消息没有显示,那么谓词就不起作用。在使用谓词的 ModelState.IsValid 验证更新我的控制器后,确实有效,但消息仍然没有显示。知道消息可能是什么问题吗? 这正是问题所在! :) 传入Must 方法的任何谓词仅在服务器端调用,而不是在客户端调用。我会更新我的答案。 好的。但是如何在服务器端验证后显示消息? (我正在使用 Html.ValidationMessageFor 助手) @CiaranGallagher:ValidationMessageFor 生成的&lt;span&gt; 标记上的data-valmsg-for 属性包含表单字段的名称(或ID,我马上忘记了)。您可以使用该命名模式将模型错误中的键与客户端上的这些验证消息相关联,这基本上是 MVC 框架在呈现剃刀模板服务器端时所做的。

以上是关于FluentValidation 谓词验证器不起作用的主要内容,如果未能解决你的问题,请参考以下文章

模型验证组件 FluentValidation

模型验证组件 FluentValidation

FluentValidation:验证仅设置了一个属性

FluentValidation 和服务器+客户端远程验证器

模拟子验证器时 FluentValidation 抛出 NullReference 异常

.NET6之MiniAPI(二十):实体验证FluentValidation