我正在对模型属性执行自定义验证。该属性是模型其他部分的代理,因此不需要明确的用户输入。服务器端验证工作正常,但不会生成客户端规则。
我已经能够成功生成客户端规则,但仅当在视图中引用该属性时才能生成客户端规则。在目标媒体资源上使用TextBoxFor
,CheckBoxFor
(或者更恰当地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)*@
答案 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