Use display and editor templates FTW!
Display and editor templates in ASP.NET MVC are often overlooked and are in fact quite powerful, here's why I think they are awesome.
Background
Display and editor templates were introduced in MVC 2 as a way to automatically build UI based on a data model. Essentially, it allows us a way to return markup required to display the data for the specified model. This is awesome because we can create templates for commonly used data models, allowing reuse and a clean razor view. The difference between display and editor templates are:
- Display templates are used for read-only HTML elements.
- Editor templates are used for editable HTML elements (e.g. input fields).
The syntax to use a template in our Razor view typically looks like this:
@Html.DisplayFor(x => x.User)
or
@Html.EditorFor(x => x.User)
Using templates
Let's create a display template and an editor template for an existing type; DateTime
.
Display templates
On our site we want all our DateTime
values to be short date format, a display template can do this for us. In views > shared
create a folder called DisplayTemplates
, adding a file called DateTime.cshtml
.
This is our display template. The template is named by the type, this is the default convention for MVC. Whatever we add to this view will be used for the DateTime
type.
@model System.DateTime
@Model.ToShortDateString()
Now whenever we have a DateTime
property we just need to use DisplayFor()
in our view.
@Html.DisplayFor(x => x.User.DateOfBirth)
Editor templates
Editing a DateTime
value requires a completely different set of HTML elements, but we can create a template for this too. In views > shared
create a folder called EditorTemplates
, adding a file called DateTime.cshtml
. Again the template is named after the type.
Adding the following code:
@model System.DateTime
@Html.DropDownListFor(model => model.Day, Enumerable.Range(1, 31).Select(i => new SelectListItem { Value = i.ToString(), Text = i.ToString() }), "Day")
@Html.DropDownListFor(model => model.Month, Enumerable.Range(1, 12).Select(i => new SelectListItem { Value = i.ToString(), Text = System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat.GetMonthName(i) }), "Month")
@Html.DropDownListFor(model => model.Year, Enumerable.Range(1900, 115).Select(i => new SelectListItem { Value = i.ToString(), Text = i.ToString() }), "Year")
This will render three dropdown elements for day, month, year. This time we use EditorFor
to render the property.
@Html.EditorFor(x => x.User.DateOfBirth)
UIHint
Now what if we want a couple of different templates for DateTime
? Instead of naming the template after the type we can give it any name and use the UIHint
attribute. We will create another display template and call it VerboseDateTime
, adding:
@model System.DateTime
@Model.ToString("dddd, d, MMMM, yyyy") // "Saturday, 27, December, 2014"
Then decorate the property with the UIHint
attribute specifying the template name.
[UIHint("VerboseDateTime")]
public DateTime DateOfBirth { get; set; }
And now we get our verbose output!
Summary
Display and editor templates allow us to create default UI markup for types or create special case templates. Think of this as a way of creating a framework for HTML representations of C# types. Much in the same way that Twitter Bootstrap is a framework for the styling of DOM elements.