2

I have an Address class that is used for both a MailingAddress and BillingAddress property in my Model. I want the MailingAddress to be required, but not the BillingAddress, but am not seeing a way to do this with 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.

Any ideas?

0

3 Answers 3

1

If your question is how to use the Required attribute in your own logic, the answer is by use of reflection. 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.

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

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your response, but I don't think that's what I am really looking for. I need to be able to have my Address class be required, but only for the MailingAddress property in the parent class it is consumed in and not for the BillingAddress property.
It's not the class that is required, but the MailingAddress property. Then you could decorate MailingAddress with [Required] in the parent class, and, instead of using typeof(Address) you'd use typeof(<parent class>) as shown above
0

This is just an odd quirk which popped into my head:

A simple solution might be to subclass Address to OptionalAddress.

I don't think the Required attributes would be inherited to the child class.

[AttributeUsage (Inherited = False)] also comes to mind if needed.

A more MVCish solution might be to implement a custom model binder (completely untested):

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;
        }

7 Comments

RequiredAttribute is only applicable to properties, parameters and fields. You do not say that a class is required, you say that one of its properties is.
I think OP wants to know how to say the properties of one instance of a class are required but of another instance are not... The two instances being properties in the same parent object.
Yeah that is how I understand it as well. The way I see it, though, sub-classing is not necessary, it is enough to decorate the property that is required with [Required]. My edited answer above reflects this.
I think with a required address in MVC you want to make sure some properties eg: Zip code are also required. I don't see your answer handling that case.
Lets not forget IValidateableObject?
|
0

Many options available at this previously asked question:

ASP.NET MVC Conditional validation

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.