Thoughts on T4MVC

In short T4MVC uses a T4 template to convert your views, actions, and controllers into types which you can reference rather than using magic strings. T4MVC essentially adds static types to your MVC project, allowing you to catch misnamed views, actions, or controllers at compile time rather than at runtime. This is a great thing, but there’s a subtle problem here which I’ll go into further below. First, a brief overview of what T4MVC does.

To return a view from an action method in MVC, you normally use a string to reference the name of the view.


public ActionResult Dashboard()
{
    return View("DashboardViewName");
}

Programmers are tortured from birth until they hate magic strings

The MVC view engine will employ some conventions and look for a file called "dashboardviewname.cshtml" in various locations. The main problem with this, is that if we rename the file, we then have to remember to change all strings which reference it. If we don’t, then our mistake won’t be noticed until runtime, when it will cause a server error.

T4MVC generates an actual C# type containing our view names, which then allows us to change this code to this.


public ActionResult Dashboard()
{
    return View(Views.DashboardViewName);
}

The Problem

This seems useful, but doesn’t actually help us. Views.DashboardViewName still refers to a magic string contained within T4MVCs generated code. So, if we rename the view file, the project will still compile, and again, there’ll be no errors until runtime. So we still have the same problem. The reason for this is that T4MVC is simply a T4 template, and it has no clue it needs to regenerate its classes. During development, we still have to remember to perform another step after renaming a view, in this case forcing the T4 template to run.

There are similar issues with action and controller names, which we can also reference through T4MVC.

My opinion is that using T4MVC’s default configuration, there’s little point in using T4MVC at all, and it can actually be detrimental to productivity. Let me define what I mean here. When you add a package like T4MVC to your project, you are adding a code complication, an extra point of maintenance, and a training requirement for developers. If you’re investing such time in a tool, it must add net value to your product. In the case of T4MVC, you’re actually adding a manual build step. This means it simply must improve the quality of your codebase in some way that justifies the time investment, and certainly must not cause any problems larger than it solves.

The Solution

So what’s the answer? One solution would be to automatically transform the T4 template as a pre-build step. An even better option would be to transform whenever something relevant changes, like the T4MVC settings file, or a controller action name. This way, T4MVC becomes a seamless solution which will always represent a strongly-typed source of truth. There’ll be a very shallow learning curve for new developers, who simply need to know how to reference views and build action urls etc in a strongly typed manner.

I was quite prepared to roll my own solution here, but there’s a great visual studio extension called AutoT4MVC which does the job nicely, running the T4MVC template on build, and whenever a controller or view changes. The fact that this is an extension initially rubbed me up the wrong way. I don’t like adding environment specific dependencies into a project. (I can’t wait for Microsoft to fix the .NET dependency graph, and allow all .NET dlls to be referenced via NuGet!). However, it’s worth noting here that since T4 transformations require the Visual Studio IDE in order to work, it’s not easy to include T4MVC as part of the build process on your build server, so if you’re using any T4 templates in a project, the transformations need to happen on a dev machine, and the results committed to the codebase. I can personally live with this, knowing that my MVC elements are all strong type references. If I change an action, or view name, the build fails straight away unless I’ve also updated all references to them. Bingo Bongo!

As an aside, my MVC projects also use RazorGenerator to pre-compile their views. So with T4MVC and RazorGenerator, we’ve moved the resolution of routes and view locations, and the compilation of views from runtime to compile time. We all make mistakes, and this setup is one way to help you catch them before your customers.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a website or blog at WordPress.com

Up ↑

%d bloggers like this: