View Engines

ASP.NET MVC is a pluggable framework with many parts that may be replaced or customized. One of these parts is the view engine. View engines assist controllers with transforming views into HTML. The view engine is a part of the ASP.NET MVC pipeline. A detailed diagram of the pipeline can be found at DotNetTricks.

MVC includes support for two default view engines. The ASPX view engine was the default for MVC 1.0 and 2.0. This is the view engine that is used by Web Forms. The Razor view engine became the default starting with MVC 3.0. This view engine leveraged a new syntax that relies heavily on the @ character. Even though the Razor view engine has been the default for more recent versions of MVC, you can still use ASPX, and both are enabled by default for an MVC project. MVC additionally allows you to disable one or both of these default view engines and enable other third party view engines such as Spark and NHaml.

You can create your own custom view engine, which is a powerful feature offered by MVC. There are three main components necessary for this: a class that implements IViewEngine, a class that implements IView, and views that leverage your custom view engine markup. After doing all of this, you will need to add your view engine (the class that implements IViewEngine) to the list of view engines in the Application_Start method of Global.asax.cs. When experimenting with view engines, I followed along with a fine example from Code Project.

When creating a class that implements IViewEngine, you can inherit from the VirtualPathProviderViewEngine, which provides some of the default behavior for you. One of the key things that you will want to accomplish with this class is to specify the location of your views. If you will still be using one or both of the default view engines alongside your custom view engine, you will need to be careful to specify a unique location or different file extension for your custom views, so that they will not be mistaken for Razor or ASPX views. Below is an example of how to specify the view location within the constructor of the class implementing IViewEngine. It searches for templates in the default location, but with the .tmpl extension.

The class that implements IView is where a lot of the action takes place. It is here that you will need to provide your special template parsing logic. The job of this code will be to find a given markup and replace it with something else. In my case, I was looking for markup like “<TMPL_VAR NAME=Message>” and replacing it with the “Message” value within ViewData. I replaced the Parse method from the Code Project example with the following.

You will of course be providing a number of views that match the format that your IView class is looking for. Below is an example of what I did in my view while experimenting with view engines. This is a very rudimentary example, but it did serve to demonstrate how to implement a custom view engine.

Why would you want to use a custom view engine? Based on the search results that I found, the most frequent reason that people seem to use a custom view engine is to provide different locations to look for views. Basically, they are wanting to organize their file structure differently than the default. Another reason that you might want to implement a custom view engine is if you are particularly fond of a templating engine used in another language and you want to implement your own version for ASP.NET. This is essentially what I was doing for my example. Before working with .NET, I came from a Perl background. The examples above were the beginnings of implementing a view engine that mimiced the functionality of Perl’s HTML::Template templating engine. Implementing a templating engine from another language could be useful if you have a lot of developers that are not familiar with Razor, but are familiar with another templating engine. However, there may be a price to pay when bringing new .NET developers onboard who are already familiar with Razor. Perhaps a more likely scenario for implementing your own view engine would be to provide some functionality that makes you more productive or does something that Razor cannot do.

Regardless of your motives, one must admit that it is impressive that Microsoft offers the opportunity to customizing this aspect of the pipeline. It provides one with a great deal of power and flexibility. Although I don’t know how useful this feature will be in my own future projects, I am curious to take a peek at some of the other view engines to see how they compare and contrast to the default view engines.