Using MVC - View-Models

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:

Use View-Models

We'll start with this simple recommendation. To some of you, it might seem obvious. But it's surprising how many apps still use ViewData, the ViewBag, TempData or other channels to pass data along controllers and views.

MVC's philosophy says 'convention over configuration'. In other words, MVC poses little to no barriers for you to implement things your way. But there are a few good conventions worth obeying. They pay themselves off over time. Including using view-models.

In the MVC sample site, we've implemented a few view-models. They brought reusability, fault tolerance and testability of views.

The first use case for a view-model was the About us page.

Here, we've created the FactAboutUsViewModel as a wrapper view-model. We added a simple boolean flag to allow the view to render images on left- or right-hand side, depending on whether the current FactAboutUs collection item is odd or even.

public class FactAboutUsViewModel
{
    public FactAboutUs Fact { get; set; }
    public bool Odd { get; set; }
}

But why a view-model? Because the information about being odd or even is neither semantically related to the model, nor is it entirely bound to the view. Hence, we haven't added that information to the content type nor have we let it passed along through ViewData or the ViewBag respectively.

At the end of the day, we have a nice artifact to distinguish odd and even facts, no matter where and how we display that 'About us' content.

Another nice example of a view-model is the CafesViewModel:

public class CafesViewModel
{
    public List<Cafe> CompanyCafes { get; set; }

    public List<Cafe> PartnerCafes { get; set; }
}

We've implemented it to render partner cafes with- or without images.

Again, we could have used ViewData/ViewBag to capture that information. But the usage or a view-model allowed us to rely on it in another page - the Contact page.

View-Models in Uploads

When the data gets submitted by the user to the MVC application, the view-model might also bring protection against overposting. Overposting means that a malicious user submits undesired information through a POST request to the app. The view-model in MVC helps in making sure that there is no other 'poised' data being sent through. It also dictates that the type of data is correct.

In the sample app, the data collected with the 'Try a free sample' and Partnership forms gets submitted to the Engagement management service automatically. Hence, no corresponding view-models exist here.

But, we handle overposting nicely in the Product catalog page in the left-hand filter form. We use the BrewerFilterViewModel (and CoffeeFilterViewModel respectively):

public class BrewerFilterViewModel
{
    public bool Aerobie { get; set; }
    public bool Chemex { get; set; }
    public bool Espro { get; set; }
    public bool Hario { get; set; }

    public IEnumerable<string> GetManufacturerFilters()
    {
        if (Aerobie)
        {
            yield return "Aerobie";
        }
        if (Chemex)
        {
            yield return "Chemex";
        }
        if (Espro)
        {
            yield return "Espro";
        }
        if (Hario)
        {
            yield return "Hario";
        }
    }
}

MVC's default model binders do us a nice job of binding these checkbox values directly to the boolean values of the Aerobie, Chemex and other properties. Then, the GetManufacturerFilters method makes sure the appropriate filter predicates are being sent to the Kentico Cloud Delivery/Preview API service endpoint.

Wrapping Up

All in all, defining a view-model costs no time but brings lots of advantages over the ViewData/ViewBag or TempData objects. You can iterate over collections with odd/even flags, reuse the structure of the view-model in different views, test strongly typed views separately from the controller, keep from malicious POST requests etc.

What about you? Do you use view-models? If so, what are the most common reasons for you to do so? Also, would you like to be able to work with forms using the MVC view-models and Editor templates instead of the JS script (as demonstrated in the article related to Kentico 10)? Would you like to work with the uploaded data in MVC before passing it onto the Engagement management service? Your comments are welcome!

Apart from that, if you wish to share your own best practice in MVC, just go ahead and write your own article! We can put a link to it into the Contents section above.

Be sure to check out part 3 where we cover one of the most exciting features of MVC - Display templates.

Tagged:
Sign In or Register to comment.