【问题标题】:Make MVC class property/class required conditionally有条件地使 MVC 类属性/类成为必需
【发布时间】:2011-08-31 23:59:53
【问题描述】:

我有一个 Address 类,用于我的模型中的 MailingAddress 和 BillingAddress 属性。我希望 MailingAddress 是必需的,但不是 BillingAddress,但我没有看到使用 DataAnnotations 执行此操作的方法。

如果我能够在 MailingAddress 属性上设置 [Required] 属性并以某种方式定义 Address 类应该如何处理所需逻辑的逻辑,我觉得这将是一个简单的解决方案。

有什么想法吗?

【问题讨论】:

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


    【解决方案1】:

    如果您的问题是如何在您自己的逻辑中使用Required 属性,那么答案就是使用反射。如果这不是你的问题,请原谅我。

    从相关类型中获取所有属性,然后查看它是否用RequiredAttribute 修饰。

    class ParentClass
    {
          [Required]
          public Address MailingAddress { get; set; }
    
          public Address BillingAddress { get; set; }
    }
    
    (...)
    
    Type t = typeof(ParentClass);
    
    foreach (PropertyInfo p in t.GetProperties())
    {
        Attribute a = Attribute.GetCustomAttribute(p, typeof(RequiredAttribute));
        if (a != null)
        {
              // The property is required, apply your logic
        }
        else
        {
              // The property is not required, apply your logic
        }
    }
    

    编辑:修正了代码中的一个错字

    编辑 2:扩展代码示例

    【讨论】:

    • 感谢您的回复,但我认为这不是我真正想要的。我需要能够要求我的 Address 类,但仅限于使用它的父类中的 MailingAddress 属性,而不是 BillingAddress 属性。
    • 这不是必需的类,而是 MailingAddress 属性。然后你可以在父类中用 [Required] 装饰 MailingAddress,而不是使用 typeof(Address) 你会使用 typeof() 如上所示
    【解决方案2】:

    这只是突然出现在我脑海中的一个奇怪的怪癖:

    一个简单的解决方案可能是将 Address 子类化为 OptionalAddress。

    我认为Required 属性不会被继承到子类。

    [AttributeUsage (Inherited = False)] 如果需要也会出现在脑海中。

    更 MVCish 的解决方案可能是实现自定义模型绑定器(完全未经测试):

    public override object BindModel(ControllerContext controllerContext,
        ModelBindingContext bindingContext)
            {
                var address = base.BindModel(controllerContext, bindingContext) as Address;
                if (bindingContext.ModelName.EndsWith("BillingAddress"))
                {
                    foreach (PropertyInfo p in address.GetType().GetProperties())
                    {
                    Attribute a = Attribute.GetCustomAttribute(p, typeof(RequiredAttribute));
                    if (a != null 
                        && propertyInfo.GetValue(address, null) == null 
                        && bindingContext.ModelState[bindingContext.ModelName 
                           + "." + p.Name].Errors.Count == 1)
                    {
                        bindingContext.ModelState[bindingContext.ModelName + "." + p.Name].Errors.Clear();
                    }
                }
                return address;
            }
    

    【讨论】:

    • RequiredAttribute 仅适用于属性、参数和字段。你不是说一个类是必需的,你说它的一个属性是。
    • 我认为 OP 想知道如何说一个类的一个实例的属性是必需的,但另一个实例的属性不是......这两个实例是同一个父对象中的属性。
    • 是的,我也是这么理解的。不过,在我看来,子类化不是必需的,用 [Required] 装饰所需的属性就足够了。我上面编辑的答案反映了这一点。
    • 我认为使用 MVC 中的必需地址,您需要确保某些属性,例如:邮政编码也是必需的。我没有看到你的答案处理这种情况。
    • 不要忘记 IValidateableObject?
    【解决方案3】:

    在这个先前提出的问题中提供了许多选项:

    ASP.NET MVC Conditional validation

    您是否需要在客户端完成此验证?

    IValidateableObject 将与您现有的任何属性一起使用,并且可以提供额外的自定义验证。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-12
      • 2018-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-03
      • 1970-01-01
      • 2015-08-12
      相关资源
      最近更新 更多