Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 3 使用FluentValidation/MVC 3在客户端上验证复选框_Asp.net Mvc 3_Fluentvalidation - Fatal编程技术网

Asp.net mvc 3 使用FluentValidation/MVC 3在客户端上验证复选框

Asp.net mvc 3 使用FluentValidation/MVC 3在客户端上验证复选框,asp.net-mvc-3,fluentvalidation,Asp.net Mvc 3,Fluentvalidation,我正在尝试使用FluentValidation验证客户端上是否选中了复选框。我想不出这是我们的生活 可以使用不引人注目的验证来完成吗?假设您有以下模型: [Validator(typeof(MyViewModelValidator))] public class MyViewModel { public bool IsChecked { get; set; } } 使用以下验证器: public class MyViewModelValidator : AbstractValidato

我正在尝试使用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");
    }
}
以相应的观点:

@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>
}
到目前为止,我们已经启动了服务器端验证并运行良好。那很好。这始终是我们必须设置的第一部分。我曾看到人们过于关注客户端验证,而忘记了服务器端验证,当你禁用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;
    }
}
到目前为止,我们已经将自定义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>

我喜欢达林·迪米特罗夫的答案,但如果你想快速回答,这里是我的替代方法

在模型中创建其他属性,例如:

public bool ValidationTrue { get; set; }
并在模型的构造函数中将其值设置为
true

在视图中使用它保存请求中的值:

@Html.HiddenFor(x => x.ValidationTrue)
现在添加如下验证规则:

public class MyViewModelValidator : AbstractValidator<MyViewModel>
{
    public MyViewModelValidator()
    {
        RuleFor(x => x.ValidationTrue)
            .Equal(true); // check it for security reasons, if someone has edited it in the source of the page

        RuleFor(x => x.HasToBeChecked)
            .Equal(x => x.ValidationTrue) // HasToBeChecked has to have the same value as ValidationTrue (which is always true)
            .WithMessage("Required");
    }
}
公共类MyViewModelValidator:AbstractValidator
{
公共MyViewModelValidator()
{
RuleFor(x=>x.ValidationTrue)
.Equal(true);//如果有人在页面源代码中编辑了它,请检查它是否安全
规则(x=>x.HasToBeChecked)
.Equal(x=>x.ValidationTrue)//HasToBeChecked必须具有与ValidationTrue相同的值(该值始终为true)
.WithMessage(“必需”);
}
}

该验证由开箱即用的不引人注目的验证器支持。

我在ASP.NET MVC5中编码,Darin的代码在涉及复选框时引用value.ToLowerCase()的行上产生javascript错误。另一个问题是,此代码使两个属性之间的客户端相等性比较无效。它似乎只在与文字值进行比较时起作用……这可能是他的意图,但我需要它在两种情况下都起作用:

这里有一个可能的解决方法,它只涉及对Darin答案的两个更改:

首先,我用以下内容更新了javascript函数。

$.validator.addMethod('equaltovalue', function (value, element, params) {
    if ($(element).is(':checkbox')) {
        value = $(element).is(':checked') ? "true" : "false";
    }
    return params.valuetocompare.toLowerCase() === value.toLowerCase();
});
其次,我用以下内容更新了EqualToValueFluentValidationPropertyValidator:

public class EqualToValueFluentValidationPropertyValidator : FluentValidationPropertyValidator
{
    EqualValidator EqualValidator 
    {
        get { return (EqualValidator)Validator; }
    }

    public EqualToValueFluentValidationPropertyValidator(ModelMetadata metadata, ControllerContext controllerContext, PropertyRule rule, IPropertyValidator validator) : base(metadata, controllerContext, rule, validator) {
        ShouldValidate = false;
    }

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() {
        if (!ShouldGenerateClientSideRules()) yield break;

        var propertyToCompare = EqualValidator.MemberToCompare as PropertyInfo;
        if(propertyToCompare != null) {
            // If propertyToCompare is not null then we're comparing to another property.
            // If propertyToCompare is null then we're either comparing against a literal value, a field or a method call.
            // We only care about property comparisons in this case.

            var comparisonDisplayName =
                ValidatorOptions.DisplayNameResolver(Rule.TypeToValidate, propertyToCompare, null)
                ?? propertyToCompare.Name.SplitPascalCase();

            var formatter = new MessageFormatter()
                .AppendPropertyName(Rule.GetDisplayName())
                .AppendArgument("ComparisonValue", comparisonDisplayName);


            string message = formatter.BuildMessage(EqualValidator.ErrorMessageSource.GetString());
            yield return new ModelClientValidationEqualToRule(message, CompareAttribute.FormatPropertyForClientValidation(propertyToCompare.Name)) ;
        }
        else
        {
            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;
        }
    }
}
公共类EqualToValueFluentValidationPropertyValidator:FluentValidationPropertyValidator
{
等速校准器等速校准器
{
获取{return(EqualValidator)验证器;}
}
公共EqualToValueFluentValidationPropertyValidator(ModelMetadata元数据、ControllerContext ControllerContext、PropertyRule规则、IPropertyValidator验证器):基本(元数据、ControllerContext、规则、验证器){
ShouldValidate=false;
}
公共重写IEnumerable GetClientValidationRules(){
如果(!ShouldGenerateClientSideRules())产生中断;
var propertyToCompare=EqualValidator.MemberToCompare as PropertyInfo;
if(propertyToCompare!=null){
//如果propertyToCompare不为null,则我们将与另一个属性进行比较。
//如果propertyToCompare为null,则我们将与文本值、字段或方法调用进行比较。
//在这种情况下,我们只关心财产比较。
变量comparisonDisplayName=
ValidatorOptions.DisplayNameResolver(Rule.TypeToValidate,propertyToCompare,null)
??propertyToCompare.Name.SplitPascalCase();
var formatter=new MessageFormatter()
.AppendPropertyName(规则.GetDisplayName())
.AppendArgument(“ComparisonValue”,comparisonDisplayName);
string message=formatter.BuildMessage(EqualValidator.ErrorMessageSource.GetString());
返回新的ModelClientValidationQualtoRule(消息,CompareAttribute.FormatPropertyForClientValidation(propertyToCompare.Name));
}
其他的
{
var验证器=(EqualValidator)验证器;
var errorMessage=new MessageFormatter()
.AppendPropertyName(规则.GetDisplayName())
.AppendArgument(“ValueToCompare”,validator.ValueToCompare)
.BuildMessage(validator.ErrorMessageSource.GetString());
var rule=new ModelClientValidationRule();
rule.ErrorMessage=ErrorMessage;
rule.ValidationType=“equaltovalue”;
rule.ValidationParameters[“valuetocompare”]=validator.valuetocompare;
收益率-收益率规则;
}
}
}
这段代码是从fluentvalidation源代码中的
EqualToFluentValidationPropertyValidator
内部类复制的,我在else之后添加了Darin的逻辑。这允许客户端验证用于属性比较和值比较…我不确定这是否是一个好方法,因为您基本上覆盖了内置的平等验证器,它可能会在未来的fluent validation版本中中断…但是
public class MyViewModelValidator : AbstractValidator<MyViewModel>
{
    public MyViewModelValidator()
    {
        RuleFor(x => x.ValidationTrue)
            .Equal(true); // check it for security reasons, if someone has edited it in the source of the page

        RuleFor(x => x.HasToBeChecked)
            .Equal(x => x.ValidationTrue) // HasToBeChecked has to have the same value as ValidationTrue (which is always true)
            .WithMessage("Required");
    }
}
$.validator.addMethod('equaltovalue', function (value, element, params) {
    if ($(element).is(':checkbox')) {
        value = $(element).is(':checked') ? "true" : "false";
    }
    return params.valuetocompare.toLowerCase() === value.toLowerCase();
});
public class EqualToValueFluentValidationPropertyValidator : FluentValidationPropertyValidator
{
    EqualValidator EqualValidator 
    {
        get { return (EqualValidator)Validator; }
    }

    public EqualToValueFluentValidationPropertyValidator(ModelMetadata metadata, ControllerContext controllerContext, PropertyRule rule, IPropertyValidator validator) : base(metadata, controllerContext, rule, validator) {
        ShouldValidate = false;
    }

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() {
        if (!ShouldGenerateClientSideRules()) yield break;

        var propertyToCompare = EqualValidator.MemberToCompare as PropertyInfo;
        if(propertyToCompare != null) {
            // If propertyToCompare is not null then we're comparing to another property.
            // If propertyToCompare is null then we're either comparing against a literal value, a field or a method call.
            // We only care about property comparisons in this case.

            var comparisonDisplayName =
                ValidatorOptions.DisplayNameResolver(Rule.TypeToValidate, propertyToCompare, null)
                ?? propertyToCompare.Name.SplitPascalCase();

            var formatter = new MessageFormatter()
                .AppendPropertyName(Rule.GetDisplayName())
                .AppendArgument("ComparisonValue", comparisonDisplayName);


            string message = formatter.BuildMessage(EqualValidator.ErrorMessageSource.GetString());
            yield return new ModelClientValidationEqualToRule(message, CompareAttribute.FormatPropertyForClientValidation(propertyToCompare.Name)) ;
        }
        else
        {
            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;
        }
    }
}
RuleFor(x => x.HasToBeChecked)
        .Equal(x => true)
        .WithMessage("Required");