ASP.NET 列表的 MVC 自定义验证<string>
ASP.NET MVC Custom validation for a List<string>
我正在使用 ASP.NET MVC 5,并且在客户端想要使用 JQuery 非侵入式验证。
以下是我的模型:
public class CompanyModel
{
public CompanyModel()
{
Employees = new List<EmployeeModel>();
}
public int CompanyId{ get; set; }
public List<EmployeeModel> Employees { get; set; }
}
public class EmployeeModel
{
public EmployeeModel()
{
Values = new List<string>();
}
public string Id { get; set; }
public string Name { get; set; }
[RequiredIf("IsRequired", true, "Atleast one value is required")]
public List<string> Values { get; set; }
public bool IsRequired { get; set; }
}
我能够在服务器端成功实现 RequiredIf 自定义属性。但我正在努力让客户端验证继续进行......
在视图中循环遍历员工列表并绑定值集合
@for (var index = 0; index < Model.Employees.Count; index++)
{
/// some other code
@for (int i = 0; i < Model.employees[index].Values.Count; i++)
{
@Html.TextBoxFor(m => m.Employees[index].Values[i], new {@autocomplete = "false" })
}
}
IsRequired 属性 是一个隐藏字段:
@Html.HiddenFor(m => m.Employees[index].IsRequired)
以下是我目前拥有的 GetClientValidationRules 方法代码。
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = ErrorMessage,
ValidationType = "requiredif"
};
rule.ValidationParameters["dependentproperty"] = (context as ViewContext).ViewData.TemplateInfo.GetFullHtmlFieldId(DependentProperty);
rule.ValidationParameters["dependentpropertyvalue"] = DependentPropertyValue.ToString().ToLower();
yield return rule;
}
我没有看到添加到 HTML 标记中的值的验证 html (data-val-*) 属性。而且我也不期望他们,因为我认为我错过了一些东西。如何获取在 html.
中填充了 data-val-requiredif 属性的值集合的所有元素
有什么想法吗?
仅供参考:html 中的相关 属性Id 像这样填充 CompanyModel。Employees_0_IsRequired for Employee[0]。
Required
验证仅确保 属性 具有值。在类似 List<string>
的情况下,这仅意味着它不为空。一个空列表仍然是一个列表,因此它可以很好地通过验证。实际上,您正在使用 RequiredIf
,并且没有提供该自定义属性的实现,但我认为它依赖于基础 Required
属性,因为我见过的几乎所有实现都.
总而言之,您需要修改 RequiredIf
实现以考虑列表的内容和其他可枚举属性,或者您需要添加一些手动验证来检查列表是否确实至少有一项。
在您的验证属性中包含 GetClientValidationRules()
方法没有什么意义,因为它的目的是将 data-val-*
属性添加到为该 属性 生成的表单控件中,而您不要为 属性 Values
生成输入(如果这样做,绑定将失败)。解决这个问题的一种方法是处理表单 .submit()
事件,检查集合中是否至少有一个项目有值,如果没有则取消提交并显示错误。
修改您的视图以包含验证消息占位符并向输入添加 class 名称以供选择
@for (var index = 0; index < Model.Employees.Count; index++)
{
....
<div class="value-group"> // necessary for relative selectors
@for (int i = 0; i < Model.employees[index].Values.Count; i++)
{
@Html.TextBoxFor(m => m.Employees[index].Values[i], new { @class="value", autocomplete = "false" })
}
@Html.ValidationMessageFor(m => m.Employees[index].Values)
</div>
}
并包含以下脚本
$('form').submit(function() { // use an id selector if you have added one to the form
var isValid = true;
var groups = $('.value-group');
$.each(groups, function(index, item) {
var group = $(this);
var inputs = group.find('.value');
if (inputs.filter(function () { return $(this).val().length > 0; }).length == 0) {
isValid = false;
group.find('span:last').append($('<span></span>').text('At least one value is required')).addClass('field-validation-error').removeClass('field-validation-valid');
}
});
return isValid;
});
您可能还想添加另一个脚本来处理每个输入的更改事件,以便在组中的任何输入现在具有值时删除关联的错误消息
我正在使用 ASP.NET MVC 5,并且在客户端想要使用 JQuery 非侵入式验证。
以下是我的模型:
public class CompanyModel
{
public CompanyModel()
{
Employees = new List<EmployeeModel>();
}
public int CompanyId{ get; set; }
public List<EmployeeModel> Employees { get; set; }
}
public class EmployeeModel
{
public EmployeeModel()
{
Values = new List<string>();
}
public string Id { get; set; }
public string Name { get; set; }
[RequiredIf("IsRequired", true, "Atleast one value is required")]
public List<string> Values { get; set; }
public bool IsRequired { get; set; }
}
我能够在服务器端成功实现 RequiredIf 自定义属性。但我正在努力让客户端验证继续进行......
在视图中循环遍历员工列表并绑定值集合
@for (var index = 0; index < Model.Employees.Count; index++)
{
/// some other code
@for (int i = 0; i < Model.employees[index].Values.Count; i++)
{
@Html.TextBoxFor(m => m.Employees[index].Values[i], new {@autocomplete = "false" })
}
}
IsRequired 属性 是一个隐藏字段:
@Html.HiddenFor(m => m.Employees[index].IsRequired)
以下是我目前拥有的 GetClientValidationRules 方法代码。
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = ErrorMessage,
ValidationType = "requiredif"
};
rule.ValidationParameters["dependentproperty"] = (context as ViewContext).ViewData.TemplateInfo.GetFullHtmlFieldId(DependentProperty);
rule.ValidationParameters["dependentpropertyvalue"] = DependentPropertyValue.ToString().ToLower();
yield return rule;
}
我没有看到添加到 HTML 标记中的值的验证 html (data-val-*) 属性。而且我也不期望他们,因为我认为我错过了一些东西。如何获取在 html.
中填充了 data-val-requiredif 属性的值集合的所有元素有什么想法吗?
仅供参考:html 中的相关 属性Id 像这样填充 CompanyModel。Employees_0_IsRequired for Employee[0]。
Required
验证仅确保 属性 具有值。在类似 List<string>
的情况下,这仅意味着它不为空。一个空列表仍然是一个列表,因此它可以很好地通过验证。实际上,您正在使用 RequiredIf
,并且没有提供该自定义属性的实现,但我认为它依赖于基础 Required
属性,因为我见过的几乎所有实现都.
总而言之,您需要修改 RequiredIf
实现以考虑列表的内容和其他可枚举属性,或者您需要添加一些手动验证来检查列表是否确实至少有一项。
在您的验证属性中包含 GetClientValidationRules()
方法没有什么意义,因为它的目的是将 data-val-*
属性添加到为该 属性 生成的表单控件中,而您不要为 属性 Values
生成输入(如果这样做,绑定将失败)。解决这个问题的一种方法是处理表单 .submit()
事件,检查集合中是否至少有一个项目有值,如果没有则取消提交并显示错误。
修改您的视图以包含验证消息占位符并向输入添加 class 名称以供选择
@for (var index = 0; index < Model.Employees.Count; index++)
{
....
<div class="value-group"> // necessary for relative selectors
@for (int i = 0; i < Model.employees[index].Values.Count; i++)
{
@Html.TextBoxFor(m => m.Employees[index].Values[i], new { @class="value", autocomplete = "false" })
}
@Html.ValidationMessageFor(m => m.Employees[index].Values)
</div>
}
并包含以下脚本
$('form').submit(function() { // use an id selector if you have added one to the form
var isValid = true;
var groups = $('.value-group');
$.each(groups, function(index, item) {
var group = $(this);
var inputs = group.find('.value');
if (inputs.filter(function () { return $(this).val().length > 0; }).length == 0) {
isValid = false;
group.find('span:last').append($('<span></span>').text('At least one value is required')).addClass('field-validation-error').removeClass('field-validation-valid');
}
});
return isValid;
});
您可能还想添加另一个脚本来处理每个输入的更改事件,以便在组中的任何输入现在具有值时删除关联的错误消息