2011-09-07 79 views
6

如何在MVC 3框架中使用客户端验证以及服务器端验证来禁用JS时如何创建条件所需的属性?例如:MVC 3有条件所需的属性

public class PersonModel 
{ 
    [Required] // Requried if Location is not set 
    public string Name {get; set;} 
    [Range(1, 5)] // Requried if Location is not set 
    public int Age {get; set;} 

    [Required] // Only required if Name and Age are not set. 
    public string Location {get; set;} 
} 

在这个例子中的规则是:

  1. NameAge如果Location没有设置是必需的。
  2. Location只有在未设置NameAge时才需要。
  3. 如果名称,年龄和位置均已设置,则无关紧要。

在视图中,如果设置了名称/年龄,则需要将结果发送到Action。如果设置了位置,则会输入另一个Action。我用两个不同的Get Url的独立表单进行了尝试;除非验证规则导致问题,否则这很有效。 Preferrably,我想使用2个独立的获取动作的URL,即

@model PersonModel 

@using(Html.BeginForm("Age", "Person", FormMethod.Post)) 
{ 
    @Html.TextBoxFor(x => x.Name) 
    @Html.ValidationMessageFor(x => x.Name) 
    @Html.TextBoxFor(x => x.Age) 
    @Html.ValidationMessageFor(x => x.Age) 
    <input type="submit" value="Submit by Age" /> 
} 

@using(Html.BeginForm("Location", "Person", FormMethod.Post)) 
{ 
    @Html.TextBoxFor(x => x.Location) 
    @Html.ValidationMessageFor(x => x.Location) 
    <input type="submit" value="Submit by Location" /> 
} 

基于上述PersonModel,如果该位置被提交,验证将失败,因为PersonModel期待的姓名和年龄是也设置。反之亦然,名称/年龄。

鉴于上面的模拟的例子,你如何创建条件所需的属性与MVC 3框架,将与客户端验证以及服务器端验证时,禁用JS?

回答

1

您可以将自定义验证添加到您的模型,子类别ValidationAttribute或实施IValidatableObject

ValidationAttribute允许您通过实现IClientValidatable并通过jQuery注册新的适配器和方法来相对简单地添加客户端验证。 见Perform client side validation for custom attribute

IValidatableObject更适合于一次性验证要求,其中重用不是一种选择。它还导致代码更简单。不幸的是,使用这种方法没有简单的方法来实现客户端验证。

0

我创建了我自己的RequiredAttribute后代。它接受一个布尔属性名称,验证的条件是什么。请注意,此代码不是生产准备好的,缺少错误检查,并且可以在检查null时进行一些改进。

[Localizable(false),AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 
public class RequiredIfAttribute : RequiredAttribute 
{ 
    public string BoolProperty { get; private set; } 
    public RequiredIfAttribute(string boolProperty) 
    { 
     BoolProperty = boolProperty; 
    } 

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     if (!Equals(value, null) || !string.IsNullOrEmpty(value as string)) 
      return ValidationResult.Success; 
     var boolProperty = validationContext.ObjectInstance.GetType().GetProperty(BoolProperty); 
     var boolValue = (bool)boolProperty.GetValue(validationContext.ObjectInstance, null); 
     if (!boolValue) 
      return ValidationResult.Success; 
     return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); 
    } 
} 

您可以创建一个只读属性来表示您的条件,如下所示。另请注意,您的代码中Age属性不能为空。如果你想支持它,你应该为该属性使用一个可为空的int(int?)类型。

public class PersonModel 
{ 
    // helper properties 
    public bool LocationNotSet { get { return string.IsNullOrEmpty(Location); } }  
    public bool NameAndAgeNotSet { get { return string.IsNullOrEmpty(Name) && Age <= 0; } } 

    [RequiredIf("LocationNotSet")] // Requried if Location is not set 
    public string Name {get; set;} 
    [Range(1, 5), RequiredIf("LocationNotSet")] // Requried if Location is not set 
    public int Age {get; set;} 

    [RequiredIf("NameAndAgeNotSet")] // Only required if Name and Age are not set. 
    public string Location {get; set;} 
}