1

I have a class (Application) that has multiple properties of the type of another custom class (Employment). I would like to validate that Employment class conditionally based on whether the property of the Application class is marked with [Required].

From what I've found, I think I should be utilizing the IValidatableObject interface for Employment. The problem is that I'm not sure how to use reflection (or something else maybe) to check if this instance of the class is annotated with the [Required] attribute to determine whether to validate it or not.

Maybe this isn't even possible. I initially set up two classes for the Employment class: Employment and EmploymentRequired. Only the latter had the validation attributes on its properties. It works, but I'd like to just have one class to use if possible.

public class Application
{
  [Required]
  public Employment Employer1 { get; set; }
  public Employment Employer2 { get; set; }
}

public class Employment : IValidatableObject
{
  [Required]
  public string EmployerName { get; set; }
  [Required]
  public string JobTitle { get; set; }
  public string Phone { get; set; }

  public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
  {
    var results = new List<ValidationResult>();
    var t = this.GetType();
    //var pi = t.GetProperty("Id");
    //var isRequired = Attribute.IsDefined(pi, typeof(RequiredAttribute));
    //how can I get the attributes of this property in Application class?
    if (isRequired)
    {
        Validator.TryValidateProperty(this.EmployerName,
            new ValidationContext(this, null, null) { MemberName = "EmployerName" }, results);
        Validator.TryValidateProperty(this.JobTitle,
            new ValidationContext(this, null, null) { MemberName = "JobTitle" }, results);
    }
    return results;
  }
}
jwynveen
  • 1,261
  • 3
  • 15
  • 34
  • you will need reference to containing application class inside employment class. By using reflection, you can check instance of this emplyment matches property employer1 / 2 of application class instance and if that property has [required] attr set, validate the employment class instance – rt2800 Sep 27 '13 at 15:11
  • possible duplicate of [Check if property has attribute](http://stackoverflow.com/questions/2051065/check-if-property-has-attribute) – Preston Guillot Sep 27 '13 at 15:14
  • @rt2800 I don't completely follow you. Could you share some code (or even pseudocode) to explain more? – jwynveen Sep 27 '13 at 15:19
  • @PrestonGuillot I grabbed some code from that question in my sample, but I'm unsure how to apply it here. I've retrieved attributes of properties like that before, but just not when nested within another class. – jwynveen Sep 27 '13 at 15:20

4 Answers4

3

You should be able to check for the required attribute using Attribute.IsDefined.

http://msdn.microsoft.com/en-us/library/system.attribute.isdefined.aspx

jasonwarford
  • 746
  • 5
  • 11
  • How do I check for the [Required] attribute in Application from within the Validate method of Employment? – jwynveen Sep 27 '13 at 15:27
1

Seems like you can't do this, because using reflection you can't get parent object/class that references your current instance and all the more so reference property information.

EDIT: Maybe you can make Employment type Generic with required and non required validation modes?

CrazyMORF
  • 268
  • 2
  • 8
0

I think you are searching for the Attribute.IsDefined method. You would have to first obtain the reference to the field itself, and then validate the presence of the attribute. Like the following (adapted from the example at MSDN):

// Get the class type (you can also get it directly from an instance)
Type clsType = typeof(Application);

// Get the FieldInfo object
FieldInfo fInfo = clsType.GetField("Employer1");

// See if the Required attribute is defined for the field 
bool isRequired = Attribute.IsDefined(fInfo , typeof(RequiredAttribute));
user1578874
  • 173
  • 1
  • 5
  • But how can I determine if a certain instance of Employment is for the property Employer1? – jwynveen Sep 27 '13 at 15:22
  • If you have a reference to the container Application object (let's suppose app), then you can simply test if app.Employer1 == your instance. – user1578874 Sep 27 '13 at 15:26
  • I am trying to do it within the Validate method of Employment, which doesn't seem to have a reference to Application. Unless you know a way I can get a reference to the parent container within that method. – jwynveen Sep 27 '13 at 15:31
  • I suppose you could use some incredibly intricate code to somehow scan your memory for references to your Employer and thereby locate the Application reference. But it seems that it would just be better coding practice to pass the Application instance along, either explicitly or by including a backreference in Employer1 to the Application class. After all, you are asking for information that is not really about the Employment instance or class, but about Application. – user1578874 Sep 27 '13 at 15:33
  • 1
    Alternatively you could also insert a new boolean field on Employment which states if it is required or not, and then set the value of this field in the initialization of the Application class (where you can use Attribute.IsDefined). – user1578874 Sep 27 '13 at 15:54
0

Since what I'm trying to do doesn't seem to be possible exactly, I found a different way to do it, based on the suggestion of @user1578874. I added an IsRequired property to Employment and used MVC Foolproof Validation to mark those properties as [RequiredIf("IsRequired")]. Seems to be the cleanest solution.

jwynveen
  • 1,261
  • 3
  • 15
  • 34