我有以下视图模型:
public class Search {
public int Id { get; set; }
[Required(ErrorMessage = "Please choose a name.")]
public string Name { get; set; }
[ValidGroup(ErrorMessage = "Please create a new group or choose an existing one.")]
public Group Group { get; set; }
}
public class Group {
public int Id { get; set; }
public string Name { get; set; }
}
我已经定义了一个自定义验证属性,如下所示:
public class ValidGroupAttribute : ValidationAttribute {
public override bool IsValid(object value) {
if (value == null)
return false;
Group group = (Group)value;
return !(string.IsNullOrEmpty(group.Name) && group.Id == 0);
}
}
我有以下观点(为简洁省略了一些):
@Html.ValidationSummary()
<p>
<!-- These are custom HTML helper extensions. -->
@Html.RadioButtonForBool(m => m.NewGroup, true, "New", new { @class = "formRadioSearch", id = "NewGroup" })
@Html.RadioButtonForBool(m => m.NewGroup, false, "Existing", new { @class = "formRadioSearch", id = "ExistingGroup" })
</p>
<p>
<label>Group</label>
@if (Model.Group != null && Model.Group.Id == 0) {
@Html.TextBoxFor(m => m.Group.Name)
}
else {
@Html.DropDownListFor(m => m.Group.Id, Model.Groups)
}
</p>
我遇到的问题是验证类input-validation-error
未应用于组输入。我假设这是因为框架正在尝试查找包含id="Group"
的字段,并且正在生成的标记具有id="Group_Id"
或id=Group_Name
。有没有办法让我上课?
http://f.cl.ly/items/0Y3R0W3Z193s3d1h3518/Capture.PNG
我尝试在组视图模型上实现IValidatableObject
而不是使用验证属性,但我仍然无法应用CSS类:
public class Group : IValidatableObject
{
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrEmpty(Name) && Id == 0) {
yield return new ValidationResult("Please create a new group or select an existing one.", new[] { "Group.Name" });
}
}
}
自我验证不起作用。我认为这是因为ValidationResult
构造函数中的第二个参数未在MVC框架中使用。
来自:http://www.devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-2
在某些情况下,您可能想要使用ValidationResult的第二个构造函数重载,它接受IEnumerable的成员名称。例如,您可能决定要在两个要比较的字段上显示错误消息,因此您将代码更改为:
return new ValidationResult( FormatErrorMessage(validationContext.DisplayName), new[] { validationContext.MemberName, OtherProperty });
如果您运行代码,您将发现绝对没有区别。这是因为虽然存在这种重载并且可能在.NET框架的其他地方使用,但MVC框架完全忽略了ValidationResult.MemberNames。
答案 0 :(得分:1)
我提出了一个有效的解决方案,但显然是一种解决方法。
我已删除验证属性并创建了自定义模型绑定器,而是手动将错误添加到属性ModelState
的{{1}}字典中。
Group.Name
当public class SearchBinder : DefaultModelBinder {
protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext,
PropertyDescriptor propertyDescriptor) {
if (propertyDescriptor.Name == "Group" &&
bindingContext.ValueProvider.GetValue("Group.Name") != null &&
bindingContext.ValueProvider.GetValue("Group.Name").AttemptedValue == "") {
ModelState modelState = new ModelState { Value = bindingContext.ValueProvider.GetValue("Group.Name") };
modelState.Errors.Add("Please create a new group or choose an existing one.");
bindingContext.ModelState.Add("Group.Name", modelState);
}
base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
}
}
// Register custom model binders in Application_Start()
ModelBinders.Binders.Add(typeof(SearchViewModel), new SearchBinder());
现在有错误条目时,CSS类正在标记中呈现。
我更喜欢在MVC中使用惯用验证的方法。
找到一种正确的方法来做到这一点。我在自我验证类中指定了错误的属性名称,因此添加到ModelState["Group.Name"]
字典的键是ModelState
。我所要做的就是更改返回的Group.Group.Name
。
ValidationResult