Channels ▼
RSS

Tools

ASP.NET MVC 5.1


Microsoft recently released ASP.NET MVC 5.1, an update to the 5.0 version it introduced with Visual Studio 2013. This update includes a few improvements that are really useful for ASP.NET MVC developers and easy to learn. In this article, I explore three enhancements included in this release: the support for enum in views, the ability to pass in Twitter Bootstrap styles, and the cumulative improvements in attribute-routing features.

Working with Enum in Views

I really like when updates include some features that developers have been awaiting since the first framework release. ASP.NET MVC 5.1 is one of these updates because it finally added straightforward support for enum in views. You could work with enums and dropdowns in previous ASP.NET MVC versions, but you had to employ a few workarounds. ASP.NET MVC 5.1 makes it easy to use an enum to display a dropdown.

The following lines show the definition of the CountryEnum with a few country names and their international dialing codes. I don't like enums to be in the Models namespace in MVC projects, but I'm using this namespace (MVC51.Models) to keep things simple for this example. I always try to have types and enums in a different namespace. In addition, I'm not considering localization requirements in this case, so the code includes just the annotations with a display name in English.

using System;
using System.ComponentModel.DataAnnotations;

namespace MVC51.Models
{
    public enum CountryEnum : byte
    {
        [Display(Name = "Australia")]
        Australia = 61,
            
        [Display(Name = "Brazil")]
        Brazil = 55,
            
        [Display(Name = "Germany")]
        Germany = 49,

        [Display(Name = "Italy")]
        Italy = 39,

        [Display(Name = "Spain")]
        Spain = 34,

        [Display(Name = "United States")]
        UnitedStates = 1,
    }
}

The following lines show the code for a very simple model that represents an incoming call and has a Country field for the previously defined CountryEnum type. Obviously, the number of fields has been simplified to allow me to focus on the use of the enum type. I haven't included annotations for validations.

using System;
using System.ComponentModel.DataAnnotations;

namespace MVC51.Models
{
    public class IncomingCall
    {
        public int Id { get; set; }

        public CountryEnum Country { get; set; }

        public DateTime DateTime { get; set; }
    }
}

I want to define a new view that allows a user to create a new incoming call (IncomingCall) and select the country value from a dropdown list. The IncomingCall class declared the Country field with the CountryEnum type, The simplest way of displaying a dropdown list in a Razor view using the new @Html.EnumDropDownListFor helper. The following lines show the code for the Home/Create.shtml Razor view that uses the new helper to generate a dropdown list displaying all the country names defined in the CountryEnum enum, thus allowing the user to select the desired value for the Country field. As you can see, it is extremely simple and straightforward to make it happen with ASP.NET MVC 5.1. You don't need to perform any conversion or use any additional helpers. However, in order to test the code, it is necessary to add a very simple controller to display the view (see Figure 1).

@model MVC51.Models.IncomingCall

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>


@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <h4>IncomingCall</h4>
        <hr />
        @Html.ValidationSummary(true)

        <div class="form-group">
            @Html.LabelFor(model => model.Country, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EnumDropDownListFor(model => model.Country, htmlAttributes: new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Country)
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

The code also takes advantage of another new feature included in ASP.NET MVC 5.1: the ability to pass in HTML attributes as an anonymous object. This way, it is possible to pass in Twitter Bootstrap styles in HtmlHelpers. For example, the following line sets the class to form-control for the generated dropdown list by assigning an anonymous object to the new htmlAttributes property.

@Html.EnumDropDownListFor(model => model.Country, 
    htmlAttributes: new { @class = "form-control" }) 

ASP.NET MVC 5.1
Figure 1: A Bootstrap dropdown list generated with the new EnumDropDownListFor HtmlHelper.

You can easily pack multiple classes and styles with the new htmlAttributes property. For example, you can specify the classes that start with the col- prefix in Twitter Bootstrap. However, if you want to specify values for the new htmlAttributes with the Html.EditorFor helper, you need to encapsulate it in another anonymous object, as shown in the next line. As you can see, the syntax is a bit different than the code shown for the Html.EnumDropDownListFor helper.

@Html.EditorFor(model => model.Country, 
    new { htmlAttributes = new { @class = "form-control" } })

It is important to notice that the new helper for enums hasn't followed many conventions that are popular with existing HTML helpers. You just have the strongly typed Html.EnumDropDownListFor. There is no Html.EnumDropDownList method. Other HTML helpers usually provide a strongly typed version (Html.TextBoxFor) and one that isn't (Html.TextBox). In addition, ASP.NET MVC 5.1 didn't include changes in the default edit templates, so if you call Html.EditorFor for an enum field, the code won't generate a dropdown list — it will insert a TextBox instead. I'll provide an example of how to solve this issue later, but I want to focus on nullable enums first.

In the previous example, the Country field wasn't nullable. Luckily, when the field related to the dropdown list is nullable, you can customize the EnumDropDownListFor HtmlHelper to display a specific option that represents a null value and will appear as the first value within the list. For example, consider a change to the definition of the Country field to make it nullable in the IncomingCall class as follows:

public CountryEnum? Country { get; set; }

You can replace the line that generated the dropdown list with the following one to set "(Unknown)" as the value that represents null in the dropdown. This option will be the first one to appear in the dropdown list. If you don't specify a desired value for null, the default is an empty string. Thus, it is convenient to specify your desired value.

@Html.EnumDropDownListFor(model => model.Country, "(Unknown)", 
    htmlAttributes: new { @class = "form-control" })

If you want to be able to automatically display a dropdown list when the field is an enum by calling the Html.EditorFor helper, you can add an Enum.cshtml template view with the following code to Views/Shared/EditorTemplates.

@model Enum

@if (EnumHelper.IsValidForEnumHelper(ViewData.ModelMetadata))
{
    @Html.EnumDropDownListFor(model => model, htmlAttributes: new { @class = "form-control" })
}
else
{
    @Html.TextBoxFor(model => model, htmlAttributes: new { @class = "form-control" })
}

The code makes a call to EnumHelper.IsValidForEnumHelper(ViewData.ModelMetadata) to make sure that there is compatibility to use the EnumDropDownListFor for the field. In case EnumHelper.IsValidForEnumHelper returns false, the code uses the helper to display a default text box. However, if you want to use the previously explained customization for nullable enums, you will have to make a call to EnumDropDownListFor for the field. You can also define another template for nullable enums and specify the templateName parameter to the EditorFor method.

In addition, if you want to manipulate a select list, there is a new EnumHelper.GetSelectList() method that returns an IList<System.Web.WebPages.Html.SelectListItem> elements that correspond to the enum constants defined in the specified enum type. You can use this method to provide the user with different ways of selecting the desired value from enum types or to display the selected value.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video