skip to content
Linkedin Twitter feed logo
16 June 2013

Three Steps to Get Fat-Razor MVC Views on Diet

Fat Razor in MVC

Let me first define the terms that I will be referring to:

Presentation Code: Is the minimal code in a view that is necessary to display visual elements, but does not take any business decision. This is a fictional simple example:

    // Business Logic Code. This code understands how the business works
    // (don't do this)
    @if (Model.IsMonthly && !Model.IsPaid && Model.Payment >= 12 && ...)
    {
	    <p>Some warning message</p>
    }
    
    // Presentation Code. This code is only concerned with whether to
    // show or hide a UI element.
    @if (Model.ShouldWarn)
    {
	    <p>Some warning message</p>
    }

Fat-Razor: I’ve coined this term to define ASP.NET Razor views with a lot of Razor/C# code that is not presentation code. This is about the Razor/C# code specifically and not about HTML/CSS/JS.

Model: This is an overloaded term. However, in this context, it is an object of data representation such as a record in the database.

Viewmodel: They are data transfer objects that are meant to be view-specific and to carry exactly what the view needs, no less and no more. Generally, viewmodels are non-reusable and each vm is meant to to be tightly coupled to one view, however, there are exceptions depending on what you are doing.

To give you a flavour of a model and a viewmodel:

// An example of a model
public class Person
{
    public Guid PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public short YearOfBirth { get; set; }
    public DateTime LastAuth { get; set; }
    // This might represent a one-to-many db relationship
    public Order[] Orders { get; set; }
}

// An example of a viewmodel
public class ProfileViewModel
{
    // Doesn't necessarily need an id

    // Combined first and last name
    public string Name { get; set; }
    // Calculated from YearOfBirth
    public short Age { get; set; }
    // E.g. "One day ago" and constructed from LastAuth
    public string LastSeen { get; set; }
    // Calculated by projections on Orders
    public short NumberOfAllOrders { get; set; }
    public short NumberOfUndeliveredOrders { get; set; }
}

Why would it hurt to have Fat-Razor views?

Before we discuss a solution, we need to agree that there is a problem.

Distribution (non-centralisation) of Business Logic

Fat-Razors carry similar criticism to what the old classical ASP had (and what PHP currently has), that is no separation of concerns. The concern of this piece of code is to show visuals and not to do business logic.

The business logic for your domain should be centralised, having Fat-Razor views highlights the use of business logic in your views, hence you are giving more control to what should be a dumb layer and violating “the power in the wrong hand” principle. You would be risking a fragile business logic that will break more often.

Due to the scope of this post, I will just tell you “It is bad, don’t do it” and won’t dive into this topic but don’t take my word for it, here is Uncle Bob’s Clean Architecture.

Unit Testing

You’ve heard it before, views aren’t unit testable (well, you can unit test them with some tools like Razor Generator but this is not the norm), or maybe more accurately shouldn’t be unit tested and should rely on different type of testing such as web testing like Visual Studio Testing Tools, Selenium or Capybara. So, Fat-Razor views mean more code you cannot unit test.

Refactoring

How many times did you change your code and compiled fine until you hit the page with your browser? And boom, your code refactoring did not propagate to the views, because it sees the views as text. Today, it is not that dramatic with tools like ReSharper, but it is still a problem. Having less C# code would reduce the problem size but not eliminate it.

Why would views become Fat-Razor views?

This is my experience of the symptoms from the industry, feel free to highlight more reasons in comments.

Using a generic model rather than a specific viewmodel

The MVC beginner tutorials try to show how simple MVC is by loading a record from the DB, transferring it into an object with an OR Mapper (Entity Framework, NHibernate and the likes) and then passing it to the view which renders it. Building a blog with MVC tutorials, I am looking at you.

Good example for beginners, gets them up to speed, but only works in trivial applications. Why? If your view is not getting exactly what it wants, then it is going to have to do some inspections on the model, hence, code and more code! If you treat the view as dumb and give it exactly what it wants, you will reduce the need for it to have any non-presentation logic.

Get your Fat-Razor into shape

Razor Ramon

Big Boss Man is my early teenage wrestling hero (he is strong and cool), but Razor Ramon fits better in this post.

Now that I have touched some of the necessary concepts around this subject, I could highlight some steps for Thin-Razor views.

1 – Use a viewmodel for your view

Do not take a model from the database and throw it directly into your view. This will couple your views to your entities and will probably invite business logic code.

My favourite way of doing this is by using a CQRS type query, this article does a good job in introducing CQRS: Introduction to CQRS. I query exactly what my view needs into a viewmodel, no intermediate model (or DTO), have a look at Dapper – a simple object mapper for .Net.

If you have a different architecture or legacy code, perhaps you could have a layer that would map a model into a viewmodel, have a look at AutoMapper, it may help.

2 – Try to differentiate business from presentation code

When writing views, always flag the question “Is this presentation code or business logic?” This is a hard question as in some cases, it might be a fine line between the two. Sometimes I ask for a second opinion and encourage a healthy debate.

3 – Package repeated presentation patterns into Html Helpers and Partial Views

Sometimes one repeats the same presentation code again and again in different views. I do that as well following the agile principle “Do the simplest thing that works, then refactor” then when I notice a pattern forming, I do refactor it into a Html Helper or a Partial View.

Conclusion

As they say “More is less”, the less code you write is the less code you have to maintain and the proper code you write will keep you safe if the developer inheriting the project, knows where you live.

I did review this post multiple times to cut it shorter, however, it is a big topic and it is still not complete. If you have any points that you would like to share, then please do comment.

2Comments
leave your own
  • Marco Cortellino June 19th, 2013

    Hi! Congratulation, your article is very interesting. I agree with you when you say do not use a model instead of a viewmodel. But really every time in the past I started to code an action using a core object as model for the view, soon or later I had to go back and change the code including a proper view model.

    So, I would like to stress the concept that almost every view should have a proper viewmodel, even if it is a dummy class with only one attribute, there is high chance that you will need to extends the class with more and more attributes in the future.

  • Old Guy July 13th, 2013

    I would like to hear from people who REALLY understand Razor and jQuery, but who still prefer to put reusable UI code in Javascript and HTML files instead of Razor. It seems to me that Razor is entirely unnecessary if you really separate concerns and use REST web services (e.g ASP.NET Web API or .ashx files).

    I really appreciate this article by Mr. Tibi as he is one of the first on the web who acknowledges the importance of less code and true separation of UI code from server code. When you create an MVC Razor project in VS, it creates 485 files, none of which I need to build a great web UI. It seems to me that the entire point of MVC is to mix UI and data logic in the most-complex and unmaintainable way possible. As Mr. Tibi has noted, all of this unnecessary “MVC” code is there so that beginners can drag-and-drop to create a sample DB app. Why would anyone who really knows jQuery and REST ever want to use Razor?

    I am reaching out to readers of this article who can point me to similar articles where experienced developers address the architectural problems with MVC and Razor. I’m looking for support to put more of our UI code in jQuery and jQuery mobile libraries so that we can REALLY reuse UI code between our diverse app set without depending on Windows and .NET DLLs. Every .NET developer in the world is against me, as if MVC and Razor are some kind of religion or something….am I delusional?

Leave a Reply

Gravatar