Using Display Templates and Editor Templates in ASP.NET MVC

Introduction

ASP.NET MVC developers often use HTML helpers such as LabelFor() and TextBoxFor() to display model properties on a view. Although this approach works fine in many situations, it proves to be inadequate when you wish to customize how data is presented to the user for displaying and for editing. Luckily, you can use display templates and editor templates to overcome this limitation. This article discusses what display templates and editor templates are and how to use them in an ASP.NET MVC application.

What Are Display Templates and Editor Templates?

When you an HTML helper, such as LabelFor() or TextBoxFor(), it displays a model property in a fixed manner. For example, LabelFor() renders a model property name in a <label> tag and TextBoxFor() renders a textbox in which a model property is shown for editing. Although this arrangement works fine in many cases, at times you need more control over the way data is shown to the end user. Consider, for example, that you have a model property that represents currency. While displaying this property value to the end user, you want to show a currency symbol such as $ along with the property value. Such a customization is not possible with the above-mentioned HTML helpers. Another example could be a DateTime model property that needs to be displayed in a specific custom format.

Luckily, ASP.NET MVC comes with templated helpers that can be used in such cases. The following helpers are available:

  • DisplayFor()
  • DisplayForModel()
  • EditorFor()
  • EditorForModel()

The DisplayFor() helper displays a model property using what is known as a Display Template. A display template is simply a user interface template that is used to display a model property. If no custom display template is provided by developers, a default one is used. The DisplayForModel() helper is similar to DisplayFor() but displays the whole model (not just a single property) using a display template. The EditorFor() helper displays a user interface for editing a model property. This user interface is known as Editor Template. The EditorForModel() helper displays the whole model for editing using a given editor template. All the helpers listed above pick a template based on the data type of a model property.

When creating views, you can use DisplayFor(), DisplayForModel(), EditorFor(), and EditorForModel() helpers even if you don't intend to have a customized user interface. Later, if you decide to have a customized interface, all you need to do is define the display and editor templates.

Just to get an idea of how these helpers work, look at the following figure:

Display Helper
Display Helper

The preceding figure shows a model property named BirthDate (System.DateTime) displayed using a custom display template and editor template respectively. This user interface is the result of the following view code :

@Html.DisplayFor(model => model.BirthDate)
@Html.EditorFor(model => model.BirthDate)

Creating and Using Display Templates

Now that you know what display and editor templates are, let's begin with an example of creating a custom display template. Create a new ASP.NET MVC application (Empty project template) and add Entity Framework Data Model for the Employees table of Northwind database. This model is shown in the following figure:

Entity Framework Data Model
Entity Framework Data Model

Then, add HomeController and Index view to the project. Next, add the following code in the Index() action method.

public ActionResult Index()
{
    NorthwindEntities db=new NorthwindEntities();
    Employee emp = db.Employees.Find(1);
    return View(emp);
}

The preceding code retrieves an Employee from the database whose EmployeeID is 1. It then passes this Employee object to the Index view. The Index view contains the following markup:

@model DisplayEditorTemplatesDemo.Models.Employee

@{
    Layout = null;
}
...
<body>
    @using(Html.BeginForm())
    {
        @Html.DisplayFor(m=>m.EmployeeID)
        @Html.DisplayFor(m=>m.FirstName)
        @Html.DisplayFor(m=>m.BirthDate)
    }
</body>
</html>

The Index view sets the model for the view to be Employee class. It then uses the DisplayFor() helper to show three model properties: EmployeeID, FirstName, and BirthDate.

At this stage, you haven't defined any custom display templates. If you run the application, you will find that the DisplayFor() helper uses default templates to output the model properties, as shown in the following figure:

Default Template
Default Template

Now, let's define some custom templates. To do so, create a Shared sub-folder under the Views folder. Then, add a DisplayTemplates sub-folder inside the Shared folder. Remember that this folder name must be DisplayTemplates. As mentioned earlier, the DisplayFor() helper looks for custom display templates inside this folder based on the data type of a model property being displayed. In the previous example, the EmployeeID, FirstName, and BirthDate properties are of type Int32, String, and DateTime respectively.

To create custom display templates, add three partial views to the DisplayTemplates folder and name them Int32.cshtml, String.cshtml, and DateTime.cshtml, respectively. Remember that the names of these display template files must reflect the data types they deal with.

Then, add the following code to the Int32.cshtml file:

@model Int32

<h1>#@Model</h1>

As you can see, this display template sets its model to be Int32. It then renders the Model property in the <h1> tag and attaches # at the beginning of the value. On the same lines, create String.cshtml and DateTime.cshtml as shown:

String.cshtml
=============

@model String

<strong>@Model</strong>
DateTime.cshtml
===============

@model DateTime

<strong>@Model.ToString("dd MMM yyyy")</strong>

Notice how the string data is being rendered by using the <string> tag and how the DateTime data is being formatted by using the dd MMM yyyy format.

If you run the application again, you will see the following in the browser:

dd MMM yyyy format
dd MMM yyyy format

Remember that once the templates are created, all the model properties of Int32 type will start using the custom display template. The same holds true for String and DateTime model properties.

Creating and Using Editor Templates

Now, let's create a custom editor template for the DateTime data type. To do so, create an EditorTemplates sub-folder under the Shared folder and add a DateTime.cshtml file there. This process is quite similar to what you did for creating display templates. Then, add the following code to the DateTime.cshtml editor template:

@model DateTime

@{
    List<SelectListItem> days = new List<SelectListItem>();
    for (int i = 1; i <= 31;i++ )
    {
        days.Add(new SelectListItem() { Text = i.ToString(), Value = i.ToString(), Selected = (i == Model.Day ? true : false) });
    }

    List<SelectListItem> months = new List<SelectListItem>();
    for (int i = 1; i <= 12; i++)
    {
        months.Add(new SelectListItem() { Text = i.ToString(), Value = i.ToString(), Selected = (i == Model.Month ? true : false) });
    }

    List<SelectListItem> years = new List<SelectListItem>();

    int prevYearCount = ViewBag.PreviousYearCount;
    int nextYearCount = ViewBag.NextYearCount;

    for (int i = Model.Year - prevYearCount; i <= Model.Year + nextYearCount; i++)
    {
        years.Add(new SelectListItem() { Text = i.ToString(), Value = i.ToString(), Selected = (i == Model.Year ? true : false) });
    }
}

@Html.DropDownList("days", days)
@Html.DropDownList("months", months)
@Html.DropDownList("years", years)

The preceding code basically renders three DropDownLists for selecting day, month, and year, respectively. The three for loops create generate a List of SelectListItem objects that contain days, months, and years, respectively. Notice how the default selection in these dropdownlists is made using the current model value and Selected property.

The year dropdownlist contains a certain number of years from the past and future. These offsets are passed from the view using the PreviousYearCount and NextYearCount ViewData / ViewBag properties.

To display the BirthDate model property using the editor template you just created, add the following code to the Index view.

@Html.EditorFor(m => m.BirthDate, new { PreviousYearCount = 10, NextYearCount = 10 })

As you can see, the preceding code uses an EditorFor() helper to show an editor for the BirthDate property. Notice how the PreviousYearCount and NextYearCount values are passed as an anonymous object. These properties are translated to equivalent ViewData entries and are accessible inside the editor template (as you did in the editor template code earlier).

If you run the application, you will see this:

The BirthDate Model Property
The BirthDate Model Property

Using DisplayForModel() and EditorForModel()

The DisplayFor() and EditorFor() helpers work for a single model property. At times, you need to render a user interface for the whole model. For example, you may have a model property that is of a complex type (say, a property that is of type Address). In such cases, you can use the DisplayForModel() and EditorForModel() helpers. These helpers pick display and editor templates based on the model type. If no template is found, they use a default template.

To see DisplayForModel() and EditorForModel() in action, add Employee.cshtml in both the folders—DisplayTemplates and EditorTemplates. Add the following markup in the Employee.cshtml from the DisplayTemplates folder:

@model DisplayEditorTemplatesDemo.Models.Employee

<table border="1" cellpadding="10">
    <tr>
        <td>Employee ID :</td>
        <td>@Model.EmployeeID</td>
    </tr>
    <tr>
        <td>First Name :</td>
        <td>@Model.FirstName</td>
    </tr>
    <tr>
        <td>Last Name :</td>
        <td>@Model.LastName</td>
    </tr>
    <tr>
        <td>Birth Date :</td>
        <td>@Html.DisplayFor(m => m.BirthDate)</td>
    </tr>
</table>

The preceding template has Employee as its model and displays the EmployeeID, FirstName, LastName, and BirthDate model properties. Notice how DisplayFor() is used to display the BirthDate property (and we have a custom template for DateTime properties).

Add the following code in the Employee.cshtml file from the EditorTemplates folder.

@model DisplayEditorTemplatesDemo.Models.Employee

<table border="1" cellpadding="10">
    <tr>
        <td>Employee ID :</td>
        <td>@Html.EditorFor(m=>m.EmployeeID)</td>
    </tr>
    <tr>
        <td>First Name :</td>
        <td>@Html.EditorFor(m => m.FirstName)</td>
    </tr>
    <tr>
        <td>Last Name :</td>
        <td>@Html.EditorFor(m => m.LastName)</td>
    </tr>
    <tr>
        <td>Birth Date :</td>
        <td>@Html.EditorFor(m => m.BirthDate)</td>
    </tr>
</table>

The previous code uses the DisplayFor() and EditorFor() helpers to render EmployeeID, FirstName, LastName, and BirthDate, respectively.

After creating the preceding templates, add the following code to the Index view.

@Html.DisplayForModel()
@Html.EditorForModel(new { PreviousYearCount = 10, NextYearCount = 10 })

Notice that the EditorForModel() helper passes an anonymous object because our custom DateTime template needs that.

If you run the application, you should see something like this:

EditorForModel()
EditorForModel()

The UIHint Attribute

When you create a display template or editor template for a data type, all the model properties of that data type start using it. At times, you may want some of the model properties of the said data type to use some different templates. You can hint your intention by using the [UIHint] attribute. The [UIHint] attribute needs to be added to the model property. To see how [UIHint] works, create another display template called DateTime2.cshtml and write the following code in it:

@model DateTime

<strong>@Model.ToString("dd / MM / yyyy")</strong>

This code displays the date in dd / MM / yyyy format instead of dd MMM yyyy format.

Now, add a metadata class for the Employee model class as shown:

public class EmployeeMetadata
{
    [UIHint("DateTime2")]
    public DateTime BirthDate { get; set; }

}

[MetadataType(typeof(EmployeeMetadata))]
public partial class Employee
{

}

Note how the [UIHint] attribute has been added to the BirthDate property. The [UIHint] attribute specifies that the DateTime2 template is to be used for this model property. If you run the application, you will see the BirthDate property being displayed like this:

BirthDate Property
BirthDate Property

Summary

Display templates and editor templates allow you to display model properties using a custom UI template. The DisplayFor(), DisplayForModel(), EditorFor(), and EditorForModel() helpers pick display / editor templates based on the data type of a model property. Custom display / editor templates are .cshtml files that you place inside DisplayTemplates and EditorTemplates folders under the Views > Shared folder. Together, they provide a flexible way to display or edit model properties as compared to helpers such as LabelFor() and TextBoxFor().

Extra Reading Links



Related Articles

Downloads

Comments

  • Saving new date value

    Posted by Dominik on 10/08/2014 03:28am

    Thanks for good template overview. What about saving new date value entered through your EditorFor dropdowns?

    • Developer

      Posted by Sean on 12/03/2014 07:51am

      Great article, and also a good question. I like how the date is split out in the editor template, but how would I then combine it back together for posting back to the server?

      Reply
    Reply
  • Dev

    Posted by Brendon Greyling on 09/19/2014 01:59am

    Great article! I'm trying it out, but I've run into some strange behaviour when I use the editorformodel helper to render an editor template I created. When MVC renders the template all my bootstrap styles are replaced with editor-field styles. Here's an example of one of the fields in the editor template: @Html.LabelFor(model = model.Line1, new { @class = "control-label col-md-2" }) @Html.EditorFor(model = model.Line1, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model = model.Line1, "", new { @class = "text-danger" }) When I render the same markup outside of the template, i.e in the parent view, all works well. Any ideas?

    Reply
  • Systems Analyst

    Posted by Dinesh on 08/11/2014 06:08am

    Good article. Learnt few good things about UI rendering in AP.NET MVC. Thank you.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Today's agile organizations pose operations teams with a tremendous challenge: to deploy new releases to production immediately after development and testing is completed. To ensure that applications are deployed successfully, an automatic and transparent process is required. We refer to this process as Zero Touch Deployment™. This white paper reviews two approaches to Zero Touch Deployment--a script-based solution and a release automation platform. The article discusses how each can solve the key …

  • On-demand Event Event Date: December 18, 2014 The Internet of Things (IoT) incorporates physical devices into business processes using predictive analytics. While it relies heavily on existing Internet technologies, it differs by including physical devices, specialized protocols, physical analytics, and a unique partner network. To capture the real business value of IoT, the industry must move beyond customized projects to general patterns and platforms. Check out this webcast and join industry experts as …

Most Popular Programming Stories

More for Developers

RSS Feeds