Using Foolproof RequiredIf with an Enum

3.6k views Asked by At

We are trying to use the Foolproof validation annotation [RequiredIf] to check if an email address is needed. We also created an enum to avoid using a lookup table id in the ViewModel. The code looks like this:

public enum NotificationMethods {
        Email = 1,
        Fax = 2
}

Then in the ViewModel:

[RequiredIf("NotificationMethodID", NotificationMethods.Email)]
public string email {get; set;}

In this senario we do not get an error when email is unfilled but selected as the notification type. Conversely this works as expected:

[RequiredIf("NotificationMethodID", 1)]
public string email {get; set;}

The only other reference to this I have found is here: https://foolproof.codeplex.com/workitem/17245

1

There are 1 answers

1
dbc On BEST ANSWER

Given that your method NotificationMethodID is returning an int, the reason your check is failing is that, in c#, each enum is its own type, inheriting from System.Enum. I.e. if you do

var value = NotificationMethods.Email;
string s = value.GetType().Name;

You will see s has the value "NotificationMethods" not "Int32".

If you try to check the equality of an int with an enum directly, you get a compiler error:

var same = (1 == NotificationMethods.Email); // Gives the compiler error "Operator '==' cannot be applied to operands of type 'int' and 'NotificationMethods'"

If you box the enum and int values first (which is what happens when they are passed to the constructor of RequiredIfAttribute) then there is no compiler error but Equals() returns false, since the types differ:

var same = ((object)1).Equals((object)NotificationMethods.Email);
Debug.WriteLine(same) // Prints "False".

To check equality of underlying integer values, you can explicitly cast NotificationMethods.Email to an integer before boxing:

var same = ((object)1).Equals((object)((int)NotificationMethods.Email));
Debug.WriteLine(same); // Prints "True"

And in the attribute application:

[RequiredIf("NotificationMethodID", (int)NotificationMethods.Email)]
public string email {get; set;}

You might also consider using const int values instead of enums:

public static class NotificationMethods
{
    public const int Email = 1;
    public const int Fax = 2;
}