Using MVC - Display Templates with Kentico Cloud

JanL@kentico.com[email protected] Czech RepublicMember, Administrator, Kentico Staff admin
edited May 2017 in Back-end Development

This is a series of articles about using MVC, mainly in relation to Kentico Cloud. Let's highlight some of the MVC artifacts and patterns that are worth using!

Contents:

Recommendations on Using Templates in Kentico Cloud

First, let's define some short names for things:

  • Conventional template: a template chosen automatically by the name of the CLR type or by the UIHintAttribute
  • Explicit template: a template chosen explicitly in a view, partial view or another template thanks to the templateName parameter of the DisplayFor method

Use Conventional Templates for Modular Content

Why? Because conventional templates get selected by the MVC runtime automatically if no other is selected (as a fallback mechanism). With that in mind, we can let business users compose pages out of modular content at will. Whatever items (of whatever type) they add to the modular content elements, those items will still be rendered successfully thanks to that fallback mechanism.

It is demonstrated in the drawing below. It depicts a fictional landing page of an online bicycle store.

The code of the view would be just:

@model BikeStore.Models.BodyPartTwoSecondaryParts

<div class="container body-part">
    @Html.DisplayFor(vm => vm.BodyPart)
</div>
<div class="container">
    <div class="inline-block half-width secondary-part">
        @Html.DisplayFor(vm => vm.FirstSecondaryPart)
    </div>
    <div class="inline-block half-width secondary-part">
        @Html.DisplayFor(vm => vm.SecondSecondaryPart)
    </div>
</div>

Noticed that the view is rather generic? It is more of a bare layout, not a hard-coded view. In the Content inventory service, marketers may pick not only bike parts but also complete bikes, accessories or repair services to the body part. To the lower secondary parts, they can put whatever 'call to action' content (the 'Redeem a code' content, some 'Buy X get Y' content, you name it) and whatever 'social content' (testimonials, reviews, both of the types together).

Using the very same view, another completely different page can be created without a touch of a developer:

With conventional templates defined for modular content, we get a unique combination of advantages that wasn't possible before:

  • the freedom for business users to compose pages themselves
  • the possibility for MVC developers to adjust the visuals
    • anytime
    • using their preferred code editor
    • without any spaghetti code
    • without generated cryptic code

Of course, not only the MVC view can be reused. Also, that modular content can be re-used in any other page.

In other words, modular content and templates bring a similar user experience as web parts and widgets do in Kentico, but are much more developer-friendly.

On a side note, you may ask why the parent view is not implemented as an MVC layout. Good question. It is because we would lose flexibility. Layouts define sections that views or partial views implement, which is good. But views must explicitly declare what their parent layouts are. This is not required with templates.

For Each Type, Define One Explicit Template for Search Results

Some content items may appear in search results listings. Here, you also cannot predict the exact types of items in the collection up front.

What you can do is to predict the context. You can have the following helper method:

public static MvcHtmlString SearchResultFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression)
{
    string typeName = expression.ReturnType.Name;

    return htmlHelper.DisplayFor(expression, $"{typeName}Search");
}

In the search results view, you can use it in a foreach loop:

@foreach (var item in Model.SearchResults)
{
    @Html.SearchResultFor(vm => item)
}

No matter the type of the item is, it still can be rendered using a proper template. In the drawing below, the downhill bike can display e.g. the 'Suspension travel (mm)' property, the electric bike may have its 'Recharging time (minutes)' property and the scooter may be decorated with 'Minimum age' and 'Maximum age' properties.

The articles may also appear in search results, alongside the products. The articles may be rendered in a completely different way (to differentiate them from other types of content).

On a side note, there are two good alternative implementations of search results. The first is to scale-out the search results page to a dedicated MVC area. With such a solution, the above helper method would not be necessary. You would be able to just rely on conventional templates. On the other hand, an area might be kind of an overkill.

As a second solution, you can implement views with inheritance according to the part 5 (coming soon). The choice depends on whether the items in the search results share common properties. The more shared properties they have, the more suitable such solution would be.

Define Explicit Templates for Other Contexts

You can extend the previous solution of search results in a way that proper templates get selected for various other contexts. As an example: A similar helper method can be written to dynamically pick suffixed templates based on a user agent string:

public static MvcHtmlString MobileFriendlyDisplayFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression, HttpRequestBase request)
{
    string userAgentFamily = SomeUserAgentsList.First(ua => ua.Id == request.UserAgent)?.Select(ua => ua.Family) ?? "DefaultUserAgent";
    string typeName = expression.ReturnType.Name;

    return htmlHelper.DisplayFor(expression, $"{typeName}-{userAgentFamily}");
}

With such a method, not only the layouts of pages but also the content itself may get rendered according to the form factor of the client device.

Wrapping Up

In this part, we've demonstrated how powerful templates are. We've shown that templates allow business users to freely compose pages with modular content. They don't have to bother the developer even when they remix most of the content in the page. And finally, as the source code of the web app isn't being generated by any tool, literally every MVC developer may step in and adjust the code anytime.

Next, we'll cover the topic of implementing inheritance in MVC views.

Tagged:
Sign In or Register to comment.