Validating Enum Values within C# MVC. Partial validation occurs - How to change validation behaviour?

Luke picture Luke · Oct 17, 2014 · Viewed 20.1k times · Source

I've been representing an enum within my razor view as a hidden field, which is posted back to an action result.

I've noticed that when it binds the string value provided within the HTML, it automatically validates the value for the enum.

/// <summary>
/// Quiz Types Enum
/// </summary>
public enum QuizType
{
    /// <summary>
    /// Scored Quiz
    /// </summary>
    Scored = 0,

    /// <summary>
    /// Personality Type Quiz
    /// </summary>
    Personality = 1
}

Razor:

@Html.HiddenFor(x => x.QuizType)

Rendered HTML:

<input data-val="true" data-val-required="Quiz Type is not valid" id="QuizType" name="QuizType" type="hidden" value="Scored">

If I change the value within the DOM to something incorrect and submit the form, ModelState.IsValid returns false and the following error is added to the ModelState:

"The value 'myincorrectvalue' is not valid for QuizType."

That's all gravy, but I thought that if I created a view model, that I had to explicitly set validation rules on my view model, such as the [Required] attribute.

Also there is a validation attribute specifically for this called EnumDataType.

[EnumDataType(typeof(QuizType))]
public QuizType QuizType { get; set; }

Question

If validation happens automatically when binding, what is the point in the EnumDataType data validation attribute?

Answer

Luke picture Luke · Oct 17, 2014

Ok, so I've found out the answer to my own question.

The error message that appeared is more of a generic error message for when the binding wasn't possible. When the binding attempts to bind a non-existent string representation of the enum value posted from the HTML to the enum, it produces the error:

The value 'myincorrectvalue' is not valid for QuizType.

The exact same error message would appear if I were to attempt to bind a string value to an int within my View Model class.

It seems that the issue is that as well as the string representation, an enum can be any integer value. I can set the enum to any number, even if that number doesn't exist within my enum.

/// <summary>
/// Quiz Types Enum
/// </summary>
public enum QuizType
{
    /// <summary>
    /// Scored Quiz
    /// </summary>
    Scored = 0,

    /// <summary>
    /// Personality Type Quiz
    /// </summary>
    Personality = 1
}

Therefore, this is valid and will be bound without error to my enum value, even though 1000 doesn't exist within my enum:

<input data-val="true" id="QuizType" name="QuizType" type="hidden" value="1000">

//  Binder will bind this just fine
QuizType = 1000

That's where the EnumDataType validation attribute comes in. If I add the validation attribute to my enum within my view model:

[EnumDataType(typeof(QuizType), ErrorMessage = "Quiz type value doesn't exist within enum")]
public QuizType QuizType { get; set;}

With the attribute in place, I will only be able to assign my valid enum values (0 or 1 for this example).

So the incorrect STRING representations posted from the HTML is validated for you automatically upon binding, but a check for any integer value will not.

I hope that this clears up validating ENUMS within ASP.NET MVC.