mvc

Using editor templates to display Drop Down Lists with enums in ASP.NET MVC

Using editor templates to display Drop Down Lists with enums in ASP.NET MVC,GET,POST,editor template,ASP.NET MVC, Enum,How does it work?
Share it:
I was prototyping an application the other day when it occurred to me that it would be really useful if the default editor template displayed enums as dropdown lists instead of text boxes. This has a few advantages:
  • If you are using an enum then you only have a limited number of valid values which makes a dropdown list more logical than a text box,
  • Automatically populating the dropdown values from the enum values saves time while prototyping,
  • It just looks cleaner.
To demonstrate this I’m going to create a simple registration form that prompts for name and gender. Let's start by creating an enum called Gender and a simple registration form 
(RegForm).

namespace MvcApplication1.Models
{
    public enum Gender : int
    {
        MALE = 1,
        FEMALE = 2
    }
 
    public class RegForm
    {
        public string Name { get; set; }
 
        public Gender Gender { get; set; }
    }
}

We’ll then create a controller (HomeController) with two actions. The first displays an empty RegForm when handling a GET request and the second re-displays the registration form when handling a POST request.
namespace MvcApplication1.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/
 
        public ActionResult Index()
        {
            return View(new RegForm());
        }
 
        //
        // POST: /Home/
 
        [HttpPost]
        public ActionResult Index(RegForm regForm)
        {
            return View(regForm);
        }
 
    }
}

We also need to create a view (Views/Home/Index.aspx) to display our model.

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.RegForm>" %>
<!DOCTYPE html>
<html>
<head runat="server">
    <title>Registration Form</title>
</head>
<body>
    <h1>Registration Form</h1>
    <% using (Html.BeginForm())
       { %>
       <%: Html.ValidationSummary() %>
       <%: Html.EditorForModel() %>
       <input type="submit" value="Submit" />
    <% } %>
</body>
</html>
We now have a basic application that displays the form as two text boxes.


 Drop Down Lists with enums in ASP.NET MVC


Next, we want to create an editor template that displays the Gender property (and all enums) as a dropdown list. If you’re not familiar with editor templates they’re partial views stored in Views/Shared/EditorTemplates. ASP.NET MVC will use these before the built-in editor templates. If it can’t find an exact match it will try the parent classes.



An Enum is the base class for all enum’s I thought this could be as easy as creating a file called Views/Shared/EditorTemplates/Enum.ascx. That approach works for int’s (except you call it Int32.ascx). Unfortunately, ASP.NET MVC uses either Gender.ascx (the name of the enum) or String.ascx as the template when displaying enums.



Most developers would give up about now and either uses the UIHint attribute on their model properties or create an editor template for each enum they define. Using UIHint would certainly be easy enough but I wanted something that was automatic. The second approach was is plain ugly and I definitely didn’t want to copy the same code into a file for each enum. The only good solution was to create a partial view called Views/Shared/EditorTemplates/String.ascx and have it detect if the model is an enum or not.

After a little bit of work I finally came up with the following:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
 
<%
    // This will be used later to decide if we display a dropdown or textbox
    SelectList selectList = null;
 
    // This code creates a select list of non-nullable enums
    if (ViewData.ModelMetadata.ModelType.IsEnum)
    {
        selectList = new SelectList(ViewData.ModelMetadata.ModelType.GetEnumNames(), Model.ToString());
    }
 
    // This code creates a select list for nullable enums
    if (ViewData.ModelMetadata.IsNullableValueType && Nullable.GetUnderlyingType(ViewData.ModelMetadata.ModelType).IsEnum)
    {
        List names = new List();
        names.Add("");
        names.AddRange(Nullable.GetUnderlyingType(ViewData.ModelMetadata.ModelType).GetEnumNames());
        selectList = new SelectList(names, Model == null ? "" : Model.ToString());
    }  
 
    // Display as a dropdown list if there is a select list, otherwise display as a textbox
    if (selectList != null)
    { %>
<%: Html.DropDownList("", selectList)%>
<%  } else { %>
<%: Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line" }) %>
<%  } %>


How does it work? 


ASP.NET MVC will automatically set the value of an enum property correctly if you pass in the name of a value. This means all I need to do is populate the dropdown list with the names of the enum values. To start I define the select list is null. This is used later to determine if we should display a dropdown or textbox.

My original solution only had the first if block which deals with non-nullable properties. If the model metadata indicates that it is an enum then it puts the name of all of the enum values into the select list and makes sure that the current value is select.

That solution worked well until I had a property that could also be null. To handle that I had to add the second if block. It’s partly because I grab the enum names a different way and partly because I want the first value in the list to be an empty string. The ASP.NET MVC framework assigns a null value to the property if it receives an empty string which allows me to set it to one of the enum values or null.

Finally, it renders a dropdown list if select list isn’t null or a textbox otherwise. I now have an elegant solution that displays enums as a dropdown list instead of a textbox. The end result is:


dropdown list

Share it:

mvc

Post A Comment:

0 comments: