C# MVC 3有条件要求的属性

C# MVC 3有条件要求的属性,c#,asp.net-mvc-3,validation,razor,C#,Asp.net Mvc 3,Validation,Razor,在禁用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;} [Requ

在禁用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;}
}
本例中的规则为:

  • 如果未设置
    位置
    ,则需要
    姓名
    年龄
  • 仅当未设置
    姓名
    年龄
    时,才需要
    位置
  • 不管姓名、年龄和地点是否都设置好了
  • 在视图中,如果设置了姓名/年龄,我需要将结果发送到
    操作
    。如果设置了位置,则执行不同的
    操作。我试过使用两个单独的表单,它们具有不同的Get Url;这非常有效,但验证规则会导致问题。我更希望使用两个单独的Get action 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" />
    }
    
    @model PersonModel
    @使用(Html.BeginForm(“年龄”、“人”、FormMethod.Post))
    {
    @Html.TextBoxFor(x=>x.Name)
    @Html.ValidationMessageFor(x=>x.Name)
    @Html.TextBoxFor(x=>x.Age)
    @Html.ValidationMessageFor(x=>x.Age)
    }
    @使用(Html.BeginForm(“Location”、“Person”、FormMethod.Post))
    {
    @Html.TextBoxFor(x=>x.Location)
    @Html.ValidationMessageFor(x=>x.Location)
    }
    
    根据上面的
    PersonModel
    ,如果提交了位置,验证将失败,因为PersonModel也希望设置姓名和年龄。姓名/年龄也一样


    在上面的模拟示例中,如何使用MVC 3框架创建条件必需的属性,当JS被禁用时,这些属性将与客户端验证和服务器端验证一起工作?

    您可以将自定义验证添加到模型的子类化或实现中

    ValidationAttribute
    允许您通过jQuery实现并注册新的适配器和方法,相对简单地添加客户端验证。 看


    IValidatableObject
    更适合于一次性验证需求,在这种需求中,重用不是一种选择。这也会导致代码更加简单。不幸的是,使用此方法无法实现客户端验证。

    我创建了自己的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属性在代码中不能为“空”。如果您想支持它,那么应该为该属性使用可为null的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;}
    }
    
    公共类PersonModel
    {
    //辅助属性
    public bool LocationNotSet{get{return string.IsNullOrEmpty(Location);}
    public bool Name和genotset{get{return string.IsNullOrEmpty(Name)&&Age