简体   繁体   English

有条件地使MVC类属性/类成为必需

[英]Make MVC class property/class required conditionally

I have an Address class that is used for both a MailingAddress and BillingAddress property in my Model. 我的模型中有一个Address类同时用于MailingAddress和BillingAddress属性。 I want the MailingAddress to be required, but not the BillingAddress, but am not seeing a way to do this with DataAnnotations. 我希望MailingAddress是必需的,而不是BillingAddress,但是我没有看到使用DataAnnotations做到这一点的方法。

If I were able to set the [Required] attribute on the MailingAddress property and somehow define the logic for how the Address class is supposed to handle the required logic, I feel like that would be a simple solution. 如果我能够在MailingAddress属性上设置[Required]属性,并且以某种方式定义了Address类应该如何处理所需逻辑的逻辑,我觉得那将是一个简单的解决方案。

Any ideas? 有任何想法吗?

If your question is how to use the Required attribute in your own logic, the answer is by use of reflection. 如果您的问题是如何在自己的逻辑中使用Required属性,则答案是使用反射。 Forgive me if that is not your question. 如果那不是你的问题,请原谅我。

Get all properties from the type in question, then see if it is decorated with a RequiredAttribute or not. 从有问题的类型中获取所有属性,然后查看其是否用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
    }
}

Edit: Fixed a typo in code 编辑:修复了代码中的错字

Edit 2: Extended code example 编辑2:扩展代码示例

This is just an odd quirk which popped into my head: 这只是一个奇怪的怪癖,突然涌入我的脑海:

A simple solution might be to subclass Address to OptionalAddress. 一个简单的解决方案可能是将Address子类化为OptionalAddress。

I don't think the Required attributes would be inherited to the child class. 我认为Required属性不会继承到子类。

[AttributeUsage (Inherited = False)] also comes to mind if needed. 如果需要,还可以想到[AttributeUsage (Inherited = False)]

A more MVCish solution might be to implement a custom model binder (completely untested): 更多的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;
        }

Many options available at this previously asked question: 这个先前提出的问题有很多可用的选择:

ASP.NET MVC Conditional validation ASP.NET MVC条件验证

Do you need this validation done on the client side or not? 您是否需要在客户端进行此验证?

IValidateableObject will be used in conjunction with any of your existing attributes and can provide for the additional custom validation. IValidateableObject将与您的任何现有属性结合使用,并可以提供其他自定义验证。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM