LA.NET [EN]

Sep 17

The MVC platform – view engines

Posted in ASP.NET MVC      Comments Off on The MVC platform – view engines

In the last post of the series, we’ve seen how PartialViewResult and ViewResult actions will end up using the response sent back to the client. We’ve also seen that these classes expose several properties that need to be set in order for them do to their work and that the Controller base class introduces several methods that will save us some work when we want to use some of the predefined default values.

Today we’ll pick up where we left. Lets start with the existing view engines…as we’ve seen, view engines are responsible for locating views and they implement the IViewEngine interface. Currently, the platform introduces 3 classes that implement this interface:

  • VirtualPathProviderEngine: this abstract class is responsible for  finding the path to a specific (partial) view. It won’t create an IView since it delegates that work to any derived class;
  • WebFormViewEngine: as you can deduce from its name, this engine is responsible for rendering ASP.NET pages (views) and user controls (partial views). This class extends the VirtualPathProvider engine and is responsible for creating an instance of the type WebFormView;
  • CompositeViewEngine: its job is to handle all the registered view engines and return the correct ViewEngineResult for the current scenario. It implements the IViewEngine interface by going through all the registered view engines and calling the appropriate method (FindView or FindPartialView) over each of those instances. When one of them returns a valid ViewEngineResult, it will return that result to the called. This is the default engine used whenever you don’t specificate  a specific engine.

Now that we’ve got a global view, it’s time to digg a little deeper into the code. As we’ve seen, the VirtualPathProvider engine is abstract and its main responsibility is getting the path to the physical ASP.NET file that contains the HTML that will be returned from the client. It introduces some important properties. The MasterLocationsFormats, PartialViewLocationFormats and ViewLocationFormats are used to hold several strings with the paths where the views are expected to be found. You can also specify which virtual provider is used. By default, you’ll get the default VirtualPathProvider, but you can always extend the class and set up the protected VirtualPathProvider property.

This class introduces two abstract methods that must be implemented by a derived class (CreatePartialView and CreateView) in order for instantiang the correct IView. As I’ve said, the WebFormViewEngine extends the VirtualPathProviderViewEngine and is responsible for initiating the locations properties (which it does so on its constructor). It will also implement the abstract methods specified before. The code is so short that I’ll just put it here:

public class WebFormViewEngine : VirtualPathProviderViewEngine {         public WebFormViewEngine() {
            MasterLocationFormats = new[] {
                "~/Views/{1}/{0}.master",
                "~/Views/Shared/{0}.master"
            }; 
            ViewLocationFormats = new[] {
                "~/Views/{1}/{0}.aspx",
                "~/Views/{1}/{0}.ascx",
                "~/Views/Shared/{0}.aspx",
                "~/Views/Shared/{0}.ascx"
            }; 
            PartialViewLocationFormats = ViewLocationFormats;
        } 
        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) {
            return new WebFormView(partialPath, null);
        } 
        protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) {
            return new WebFormView(viewPath, masterPath);
        }
    }

The WebFormView will be responsible for building an instance from the required ASP.NET resource (page or user control) and rendering the HTML. We will talk about this class in detail in the next post.

Back to the view engines, we still need to talk about the CompositeViewEngine. As I said, this is the default engine used by default. In fact, it’s not really an engine because it won’t be able to do anything by itself. What it does is maintain a collection  of IViewEngine instances. When a request comes in, it will go through all the previous registered engines and it will try to get an engine that returns a valid response for the current request. When that happens, it will return that result to the caller.

As you might expect, you can also create your own engine. In order to use it, you need to register it (probably during the application start event) by adding it to the static Engines property of the ViewEngines class:

ViewEngines.Engines.Add( new MyEngine() );

The current release of ASP.NET MVC will only register the WebFormViewEngine by default for you. One more observation: When adding a new engine, you might need to employ some sort of locking because the Add method isn’t really thread safe.

As you can see, the main function of a view engine is locating and returning a valid IView that will be responsible for rendering the response sent back to the client. On the next post we’ll take a look at how the WebFormView class does its work. Keep tuned!