How to make RequiredAttribute work with an enum field
Asked Answered
C

2

7

I've recently realized that RequiredAttribute does not work on enum fields. Let's say I have two select elements called ddlOfficers and ddlApplicationTypes on the form both rendered with the help of HtmlHelper methods. The helper method for creting ddlOfficers is as follows:

 @Html.DropDownListFor(x => x.OfficerID, Model.Officers, "<Choose>", new { id = "ddlAddressedOfficer" })

Where OfficerID is a Nullable<int>

For ddlApplicationTypes I had to write an extension method that would let me create dropdownlist for enum fields:

 @Html.EnumDropDownListFor(x => x.ApplicationType, new { @class = "select-normal" })

Where ApplicationType is of type custom enum called AppType

  public Enum AppType{
     None=0,
     Complaint,
     Query,
     Suggestion
  }

I've decorated both OfficerID and ApplicationType properties with RequiredAttribute. When I don't select anything on ddlOfficers I get validation warning on submitting. But I don't get any warning when I don't select anything on ddlApplicationType. And I probably know the cause of the problem:If I compare the two select elements I can see that the first option (Choose) of ddlOfficers has no value specified, which when selected causes the validation to complain. But the first option of ddlApplicationType has value of "None". So the validation engine sees that the selected option has a value and simply ignores it. What would you suggest to do to get it working?

EDIT: To make things more clear to see here is the html for both select elements:

<select class="select-normal input-validation-error" data-val="true"  data-val-required="Choose the addressed officer" id="ddlOfficers" name="OfficerID">
   <option value="">&lt;Choose&gt;</option>
   <option value="1">Ben Martin</option>
   <option value="2">Nick Carter</option>
   <option value="3">Sebastian Van</option>
</select>

<select class="select-normal valid" data-val="true" data-val-required="Select the application type" id="ddlApplicationType" name="ApplicationType">
   <option selected="selected" value="None">&lt;Choose&gt;</option>
   <option value="Complaint">Complaint</option>
   <option value="Query">Query</option>
   <option value="Suggestion">Suggestion</option>
</select>
Cherubini answered 28/8, 2014 at 12:24 Comment(2)
If its your own helper method, you could modify it to generate the first option element with no value - which might look like <option value>-- select --</option>. If ApplicationType is a nullable enum with the [Required] attribute, then it should be invalid if the first option is selected.Meiosis
@StephenMuecke, I wish you'd posted this as an answer. I followed your tip and reached the goal. Thank you.Cherubini
W
13

There's nothing wrong with your custom helper. The HTML clearly shows that the required data validation has been added (data-val-required). Simply, the issue is that that your enum always has an acceptable value. You may not consider None acceptable, but from the enum's perspective, it's just fine. So you have two choices:

  1. Add your own custom validation to ensure that None is not selected. You'll need to handle this both client and server-side, because you're completely on your own here.

  2. If you can change the enum, you can remove the None option, and then simply use a nullable enum on your model/view model property, i.e.:

    public AppType? ApplicationType { get; set; }
    

    Then, the required validation will work as expected.

Wickliffe answered 28/8, 2014 at 14:11 Comment(1)
Just to add the the reason the Nullable enum above works is that it changes the default value on the drop down to empty string rather than the value of zero (if its an ordinary non nullable enum , ie an int). A int of zero will pass the Required attribute check, whereas a nullable int with a null (empty string) will not pass.Carefree
P
3
[EnumDataType(typeof(AppType))]

This class lets you map the underlying value in a column to a corresponding enumeration constant name. This lets you define an enumeration that contains descriptive values that correspond to database values, and then use the enumeration constant names instead of the database values when data is displayed.

public enum ReorderLevel
{
    Zero = 0,
    Five = 5,
    Ten = 10,
    Fifteen = 15,
    Twenty = 20,
    TwentyFive = 25,
    Thirty = 30
}

[MetadataType(typeof(ProductMD))]  
public partial class Product
{  
    public class ProductMD
    {  
        [EnumDataType(typeof(ReorderLevel))]  
        public object ReorderLevel { get; set; }  
    }  
} 

EnumDataTypeAttribute MSDN Article

Provocative answered 16/11, 2016 at 4:19 Comment(1)
“While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.”Tinderbox

© 2022 - 2024 — McMap. All rights reserved.