Using Display and Editor Templates in ASP.NET MVC

Today, we discuss how Display and Editor Templates keep your custom MVC form fields consistent in your web application.

Written by Jonathan "JD" Danylko • Last Updated: • MVC •
Display/Editor Templates

If you've worked with forms before in ASP.NET MVC, you know if you have a duplicate input and display field in a model across multiple screens, most users perform the old "copy and paste" HTML from one view to another. If you need to display an image or a model with various types, how would you display, or even edit, that model?

Regardless of whether you use one field or one model, ASP.NET MVC provides various techniques on how to display and edit data types.

Overview

The techniques I refer to are the Display and Editor helpers. They include:

  • DisplayFor() - Display HTML based on a specific type
  • DisplayForModel() - Display HTML for a specific model type
  • EditorFor() - Allow editing HTML based on a specific type
  • EditorForModel() - Allow editing HTML base on a specific model type

The entire idea of using these helper methods is to keep a consistent interface throughout your entire application.

Let's start with an example for our Display methods.

If we have the following model for our View,

public class ExampleViewModel
{
    public string FirstName { getset; }
    public string LastName { getset; }
    public DateTime LastLogon { getset; }
}

and in our View, we use a display helper like this,

@Html.DisplayFor(e=> e.LastLogon)

Mvc would look in the \Views\Shared\DisplayTemplates\<type>.cshtml and load that into your View. Yes, it can get that granular.

If we did have a DateTime.cshtml in that directory, it would probably look like this:

Views\Shared\DisplayTemplates\DateTime.cshtml

@String.Format("{0:D}", Model) @* Thursday, 10 April 2008 *@

Whatever type you need for displaying (or editing) data, these HtmlHelpers act just like an @Html.Partial("/Views/Shared/DisplayTemplates/DateTime.cshtml", Model.LastLogon) only it's based more on the data type as opposed to just calling a partial view.

For the EditorFor(), you would create an EditorTemplates folder under the Shared folder (just like the DisplayTemplates) and place a DateTime.cshtml file in there which would look like this:

Views\Shared\EditorTemplates\DateTime.cshtml

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line", type = "datetime" })

Now, every time you write EditorFor() for a DateTime field, this template is what will render out to the View. The same is true for the DisplayFor(). They're made for specific data types.

DisplayForModel() and EditorForModel()

The same is true with the DisplayForModel() and EditorForModel().  

Let's continue with our ExampleViewModel from above. We can place an ExampleViewModel.cshtml in the DisplayTemplates folder that looks like this:

Views\Shared\DisplayTemplates\ExampleViewModel.cshtml

@model DanylkoWeb.ViewModel.ExampleViewModel
<div class="row">
    @Html.LabelFor(e=> e.FirstName)
    @Html.DisplayFor(e=> e.FirstName)
</div>
<div class="row">
    @Html.LabelFor(e => e.LastName)
    @Html.DisplayFor(e => e.LastName)
</div>
<div class="row">
    @Html.LabelFor(e => e.LastLogon)
    @Html.DisplayFor(e => e.LastLogon)
</div>

If you want to make them editable, replace each DisplayFor() with EditorFor() and you're done.

Bootstrap Pagination

Everyone is using Bootstrap nowadays and they have a way to style your paging as shown on their site.

There is a way to make a custom pager using DisplayTemplates. One thing you need to pull this off is the MvcPaging library which can be found in the NuGet repository.

Open the Package Manager Console in Visual Studio (View/Other Windows/Package Manager Console) and type:

Install-Package MvcPaging

Once that's installed, you can use paging on any of your Views.

@Html.Pager(Model.Posts.PageSize, Model.Posts.PageNumber, Model.Posts.TotalItemCount).Options(o => o.DisplayTemplate("BootstrapPagination"))

Notice at the end of the chain, we have an Options method that can define a DisplayTemplate for us.

"So what does the BootstrapPagination.cshtml file look like?"

I'm glad you asked.

Views\Shared\DisplayTemplates\BootstrapPagination.cshtml

@model PaginationModel
<div class="text-center">
    <ul class="pagination pagination-sm">
        @foreach (var link in Model.PaginationLinks)
        {
            @BuildLink(link)
        }
    </ul>
</div>
@helper BuildLink(PaginationLink link)
{
    var liBuilder = new TagBuilder("li");
    if (link.IsCurrent)
    {
        liBuilder.MergeAttribute("class""active");
    }
    if (!link.Active)
    {
        liBuilder.MergeAttribute("class""disabled");
    }
    var aBuilder = new TagBuilder("a");
    aBuilder.MergeAttribute("href", link.Url ?? "#");
    // Ajax support
    if (Model.AjaxOptions != null)
    {
        foreach (var ajaxOption in Model.AjaxOptions.ToUnobtrusiveHtmlAttributes())
        {
            aBuilder.MergeAttribute(ajaxOption.Key, ajaxOption.Value.ToString(), true);
        }
    }
    aBuilder.SetInnerText(link.DisplayText);
    liBuilder.InnerHtml = aBuilder.ToString();
    @Html.Raw(liBuilder.ToString())
}

Of course, we should place this BuildLink into an HtmlHelper, but I decided to include it in the View for quick demo purposes.

Now you can customize your paging control to any way you like using HTML and CSS.

Conclusion

In this post, we covered the basics of how to setup DisplayFor(), DisplayForModel(), EditorFor(), and EditorForModel() using the DisplayTemplates and EditorTemplates folders and took it one step further by using the MvcPaging library to create a custom Bootstrap pagination display type.

The best way to keep your interface consistent in your application is to provide each complex type or model with familiar groupings in your Views.

Display and Editor Helpers provide a quick and easy way to make your application more modular using specific Views for your data types.

Did you find a better way to create slicker DisplayFor() or EditorFor() Helpers? Post your comments below.

ASP.NET 8 Best Practices on Amazon

ASP.NET 8 Best Practices by Jonathan Danylko


Reviewed as a "comprehensive guide" and a "roadmap to excellence" with over 120 Best Practices for ASP.NET Core 8, Jonathan's first book by Packt Publishing explores proven techniques for every phase of the SDLC.

Learn industry-standard concepts to improve your coding, debugging, and deployment of ASP.NET Core websites.

Order now on Amazon.com button

Picture of Jonathan "JD" Danylko

Jonathan "JD" Danylko is an author, web architect, and entrepreneur who's been programming for over 30 years. He's developed websites for small, medium, and Fortune 500 companies since 1996.

He currently works at Insight Enterprises as an Architect.

When asked what he likes to do in his spare time, he replies, "I like to write and I like to code. I also like to write about code."

comments powered by Disqus