验证ViewModel中的对象不添加CSS验证类

时间:2012-01-13 00:06:48

标签: c# .net asp.net-mvc-3 validation

我有以下视图模型:

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" });
        }
    }
}

更新2

自我验证不起作用。我认为这是因为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。

1 个答案:

答案 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