从视图中排除模型属性时,不输出MVC客户端验证规则

时间:2016-06-21 12:49:41

标签: asp.net-mvc validation

我正在对模型属性执行自定义验证。该属性是模型其他部分的代理,因此不需要明确的用户输入。服务器端验证工作正常,但不会生成客户端规则。

我已经能够成功生成客户端规则,但仅当在视图中引用该属性时才能生成客户端规则。在目标媒体资源上使用TextBoxForCheckBoxFor(或者更恰当地HiddenFor)。然而,这感觉就像一个黑客,因为该物业甚至没有一个二传手,所以保证价值被丢弃。

有没有办法强制ASP.NET MVC为特定属性生成客户端验证规则而不在视图中使用它?

示例代码

public class Model {
    public bool Option1 { get; set; }
    public bool Option2 { get; set; }
    public bool Option3 { get; set; }

    [CustomValidator(ErrorMessage = "Validation Failed!")]
    public bool AtLeastOneSelected => Option1 != false || Option2 != false || Option3 != false;
}

public class CustomValidator : ValidationAttribute, IClientValidatable {
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
        // breakpoint below
        return new List<ModelClientValidationRule>();
    }
}

示例视图

@Html.CheckBoxFor(m => m.Option1)
@Html.CheckBoxFor(m => m.Option2)
@Html.CheckBoxFor(m => m.Option3)
@Html.ValidationMessageFor(m => m.AtLeastOneSelected)

@*//Client rules will not be generated without this line*@
@*//@Html.TextBoxFor(m => m.AtLeastOneSelected)*@

2 个答案:

答案 0 :(得分:0)

这里唯一的问题是客户端验证无法开箱即用。这是因为验证客户端必须绑定到表单字段。必须存在触发有效/无效确定的内容,并且没有表单字段,您无需执行此操作。

您始终可以编写一些自定义客户端验证。只需检查您的选项并查看是否设置了至少一个选项,然后相应地添加/删除邮件。您可以查看require_from_group的jQuery验证文档(MVC中客户端验证的背后原因)。在这个特定的例子中,这似乎就像你想要的一样。您只需手动添加规则。

$( "#myform" ).validate({
  rules: {
    Option1: {
      require_from_group: [1, ".options"]
    },
    Option2: {
      require_from_group: [1, ".options"]
    },
    Option3: {
      require_from_group: [1, ".options"]
    }
  }
});

然后,您只需要将该类添加到每个选项字段中。

答案 1 :(得分:-1)

我遇到了类似的问题,因为一些愚蠢的UI要求,除了自己的验证之外我还必须验证三个输入。

我确实设法让它与所有内置的东西一起工作,而不需要任何黑客攻击。

我需要ValidationAttribute

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Web.Mvc;

namespace ValidationAttributes
{
    public sealed class MyValidationRule : ValidationAttribute, IClientValidatable
    {
        public MyValidationRule()
            : base("My validation rule's error message {0}")
        {
            // initialise vars here
        }

        public override bool IsValid(object value)
        {
            var valid = value == null;

            // validate logic here

            return valid;
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            yield return new ModelClientValidationMyValidationRule(FormatErrorMessage("SomeValueFor0ParamAbove"), MinimumAgeInYears);
        }
    }
}

...和ModelClientValidationRule

using System.Globalization;
using System.Web.Mvc;

namespace ModelClientValidationRules
{
    public class ModelClientValidationMyValidationRule : ModelClientValidationRule
    {
        public ModelClientValidationMyValidationRule(string errorMessage)
        {
            ErrorMessage = errorMessage;
            ValidationType = "myvalidatorrule";

            // add any params needed on the client side from the server side by using the following
            ValidationParameters.Add("param_name", "param_value");
        }
    }
}

...我需要在我的模型中添加道具

[MyValidationRule]
public whatever SomeProperty { get; set; }

...我需要在视图中添加客户端验证

@Html.ValidationMessageFor(x => x.SomeProperty, "Validation message")

...最后我需要在我的脚本中包含一些js

jQuery.validator.addMethod("myvalidationrule", function (value, element, params) {
    var valid = false;

    // your validation logic goes here
    // NB element will be undefined as the validator is not driven by an element

    return valid;
});

jQuery.validator.unobtrusive.adapters.add("myvalidationrule", function (options) {
    options.rules["myvalidationrule"] = options.params;
    options.message["myvalidationrule"] = options.message;
});

我真的希望这有道理......:S