Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Keep Your Views Clean with Display Templates

0.00/5 (No votes)
5 Jan 2016 1  
In this post, we'll discuss how display templates can simplify our view logic.

Display templates (along with Editor templates) are a powerful feature of ASP.NET MVC. They allow us to create reusable HTML snippets, much like we do with partial views. In this post, we'll discuss how display templates can simplify our view logic. We'll display a collection of data without a single foreach loop in sight.

Let's say we have a page that needs to display a table of products. Each product has a description, colour and price. We also need to calculate and display the total price of all products. We'll create a ViewModel for this page to hold our product data. We'll also create a separate ViewModel for each product.

Here's what our ShowProductsViewModel looks like:

public class ShowProductsViewModel
{
    public IEnumerable<ProductViewModel> Products { get; set; }
    public int TotalPrice { get; set; }
}

Our individual ProductViewModel looks like this:

public class ProductViewModel
{
    public int ProductId { get; set; }
    public string Description { get; set; }
    public string Colour { get; set; }
    public decimal Price { get; set; }
}

Before we get into the nitty gritty of displaying our data, we need a view to display it. We also need a controller to retrieve the data, create the ViewModel and bind it to the view. Let's use a ProductController and a ShowProducts view. To keep things simple, let's assume we're fetching our products from a business service. Ignoring the implementation of this service, here’s what the interface might look like:

public interface IBusinessService
{
    IList<Product> GetProducts();
}

We'll do some simple mapping inside the controller to ready our data for the view. It's outside the scope of this post, but at this point I would tend to pass this work off to a factory.

public class ProductController : Controller
{
    using System.Linq;

    private IBusinessService businessService;

    public ProductController()
    {
        businessService = new BusinessService();
    }

    public ActionResult ShowProducts()
    {
        var products = businessService.GetProducts();	// fetch our products from a 
							// business service somehow
        var model = new ShowProductsViewModel
        {
            Products = products.Select(MapProduct)
            TotalPrice = products.Sum(x => x.Price)
        };
        return View(model);
    }

    private ProductViewModel MapProduct(Product source)
    {
        var productViewModel = new ProductViewModel
        {
            ProductId = source.Id,
            Description = source.Description,
            Colour = source.Colour,
            Price = source.Price
        };
        return productViewModel;
    }
}

Now that we have our scaffolding set up, how can we approach this? We could loop through our product collection inside our view with a foreach. The problem I have with this approach is that it introduces code logic into the view. Granted, it's only a single foreach loop, but there is a far more elegant way to handle this.

Enter the Display Template

If your project doesn't have one already, create a DisplayTemplates folder within Views/Shared. Now create a partial view called ProductViewModel.cshtml and set the Model as ProductViewModel. The standard naming convention is to give the partial the same name as the model. You can provide a different name if you wish and pass the name of the template at display time. We are going to display our products in a table, so our display template is nice and simple. It just contains the table row for our product:

@model ProductViewModel

<tr data-productid="@Model.ProductId"> <!-- in case we need to reference our row later -->
    <td>@Model.Description</td>
    <td>@Model.Colour</td>
    <td>@Model.Price</td>
</tr>

Finally, we come to our view. To use the display template, we call the Html.DisplayFor extension method:

@model ShowProductsViewModel
@ {
    Layout = "~/Views/Shared/_Layout.cshtml"
}

<table>
    <thead>
        <tr>
            <th>Description</th>
            <th>Colour</th>
            <th>Price</th>
        </tr>
    </thead>
    <tbody>
        @Html.DisplayFor(m => m.Products)
    </tbody>
</table>
<p><span>@Model.TotalPrice</span></p>

In summary, what did we cover just now?

  • We mapped some data from our business service to a ViewModel inside our controller (we could have used a factory for this)
  • We created a display template to display a single product
  • We created a view to display all our product data
  • We used the DisplayFor extension method to invoke our display template on our products
  • We had no need for a foreach loop, anywhere, resulting in a much cleaner view

View the original article

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here