【发布时间】:2015-12-10 22:38:28
【问题描述】:
我创建了一个自定义组验证器,以确保用户至少填写了给定组中的一个字段。这在我加载页面并提交表单而不输入任何内容时有效。
无效的表格
有效形式
但是,问题在于表单出现除组验证错误之外的任何错误。当我强制表单显示组所需的验证错误,然后在组中的一个字段上显示字符串长度错误时,组验证错误不会消失。
经过一些调试,我相当确定它的客户端验证无法正常工作,因为它不会在生成客户端验证时消除服务器端验证错误。当表单生成字符串长度错误时,它会阻止将表单发布到服务器,这将删除需要组验证的错误。
任何人都可以看到客户端验证代码的问题吗?我从这个 stackoverflow 页面MVC3 unobtrusive validation group of inputs 复制了代码,并对其进行了更改以满足我的需要。这是我第一次尝试自定义验证,如果问题非常简单,请原谅我。另一个指标是,每当我输入然后删除单个字符时,组验证错误不会打开/关闭。
我在下面提供了自定义验证器代码:
自定义验证器 C#(服务器端和客户端)
public class RequireAtLeastOneIfAttribute : ValidationAttribute, IClientValidatable
{
private string[] Properties { get; set; }
public RequireAtLeastOneIfAttribute(params string[] properties)
{
Properties = properties;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if(Properties == null || Properties.Length < 1)
{
return null;
}
foreach (var property in Properties)
{
var propertyInfo = validationContext.ObjectType.GetProperty(property);
var propertyValue = propertyInfo.GetValue(validationContext.ObjectInstance, null);
if (propertyInfo == null)
{
return new ValidationResult(string.Format("Unknown property {0}", property));
}
if (propertyValue is string & !string.IsNullOrEmpty(propertyValue as string))
{
return null;
}
if (propertyValue != null)
{
return null;
}
}
return new ValidationResult("At least one age group field is required");
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = ErrorMessage,
ValidationType = "requireatleaseoneif"
};
rule.ValidationParameters["properties"] = string.Join(",", Properties);
yield return rule;
}
}
Javascript
我对 javascript 所做的唯一更改是 id。
jQuery.validator.unobtrusive.adapters.add(
'requireatleaseoneif', ['properties'], function (options) {
options.rules['requireatleaseoneif'] = options.params;
options.messages['requireatleaseoneif'] = options.message;
}
);
jQuery.validator.addMethod('requireatleaseoneif', function (value, element, params) {
var properties = params.properties.split(',');
var values = $.map(properties, function (property, index) {
var val = $('#' + property).val();
return val != '' ? val : null;
});
return values.length > 0;
}, '');
剃须刀
@Html.RadioButtonFor(m => m.HaveDependants, true, new { id = "borrower-haveDependants-true", @class = "block-radio-input" })
@Html.RadioButtonFor(m => m.HaveDependants, false, new { id = "borrower-haveDependants-false", @class = "block-radio-input" })
@Html.ValidationMessageFor(m => m.HaveDependants)
@Html.LabelFor(m => m.DependantsAgeGroupOne)
@Html.TextBoxFor(m => m.DependantsAgeGroupOne, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.DependantsAgeGroupOne)
@Html.LabelFor(m => m.DependantsAgeGroupTwo)
@Html.TextBoxFor(m => m.DependantsAgeGroupTwo, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.DependantsAgeGroupTwo)
@Html.LabelFor(m => m.DependantsAgeGroupThree)
@Html.TextBoxFor(m => m.DependantsAgeGroupThree, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.DependantsAgeGroupThree)
我还认为问题可能在于其触发方式。因为验证属性不在文本输入本身上,而是在单选按钮上,所以我添加了以下 javascript 以在按钮单击时验证整个表单。
<script>
$(document).ready(function () {
$(form).validate;
});
</script>
我把 Javascript 的最后一位改成如下
$('input').blur(function () {
$('.haveDependants').valid();
})
【问题讨论】:
-
一半的服务器端代码丢失。此外,通过更改 javascript 代码中的“id”,您的意思是您决定应该将有意义的名称
atleastonerequired更改为不正确的名称requireatleaseoneif?干得好! -
你需要把你的两分钱放进去吗?你的回答没有帮助。如果你知道这个洞的故事,那确实是有道理的。 'requireatleastoneif - 单选按钮设置为 true。因此,将来您可以将您的智能 cmets 留给自己。谢谢!
-
您的代码存在一些潜在问题。无论
HaveDependants的值如何,验证都将被触发,并且我假设您只希望它在名称 RequireAtLeastOneIf 所指示的值为 true 时触发(您实际上在哪里检查该值)。如果这是一个复杂对象的一部分,因为您使用了var val = $('#' + property).val();,下一次验证将失败。但是您显示的最后一个脚本只是在首次加载文档时验证表单,而不是单击按钮您发布了正确的代码吗? -
是的,我的意图是仅验证单选按钮是否为真,但我试图让客户端组验证按原样工作。从那以后我想到最后一段 JavaScript 是错误的。我已将新代码添加到问题中,但这也不起作用。
-
@CodeMonkey(看看这条评论是如何开始的)。您的单选按钮没有
class='haveDependants',所以$('.haveDependants').valid();什么都不做,因为没有具有该类名的元素
标签: asp.net-mvc validation unobtrusive-validation asp.net-mvc-validation