【问题标题】:MVC 3 Conditionally Required PropertiesMVC 3 有条件的必需属性
【发布时间】:2011-11-12 04:46:59
【问题描述】:

当禁用 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. 如果未设置 Location,则需要 NameAge
  2. 仅当未设置 NameAge 时才需要 Location
  3. 无论姓名、年龄和位置是否都已设置。

在视图中,如果设置了名称/年龄,我需要将结果发送到Action。如果设置了位置,则为不同的Action。我尝试过使用 2 种不同 Get Url 的单独表格;除了验证规则引起问题外,这很好用。最好,我想使用 2 个单独的 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" />
}

根据上面的PersonModel,如果提交了位置,验证将失败,因为 PersonModel 期望同时设置名称和年龄。姓名/年龄反之亦然。

鉴于上述模拟示例,您如何使用 MVC 3 框架创建条件要求的属性,以便在禁用 JS 时与客户端验证以及服务器端验证一起使用?

【问题讨论】:

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


    【解决方案1】:

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

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

    IValidatableObject 更适合不能重复使用的一次性验证要求。它还导致代码更简单。不幸的是,使用这种方法实现客户端验证并不容易。

    【讨论】:

      【解决方案2】:

      我创建了自己的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;}
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-03
        • 1970-01-01
        • 2013-12-27
        • 2012-09-16
        • 1970-01-01
        相关资源
        最近更新 更多