ASP.NET MVC Tip #19 – Use the nVelocity View Engine

In this tip, I demonstrate how you can use the nVelocity view engine, instead of the normal Web Forms view engine, when displaying views from an ASP.NET MVC application.

By default, you build views for an ASP.NET MVC application by creating ASP.NET Web Form pages (.aspx files). You are not required to do this. If you prefer, you can swap out the Web Forms view engine and use an alternative view engine. In this tip, I demonstrate how you can use the nVelocity view engine.

Why would you want to use the nVelocity view engine instead of the normal Web Forms view engine? You might be motivated for a couple of different reasons. First, nVelocity is a port of the Java Apache Software Foundation Velocity project to the .NET framework. If you are migrating an existing Java application to .NET, and the existing application was written with the Velocity template engine, then using the nVelocity view engine can make the migration process much smoother.

Second, you might prefer the template syntax of nVelocity over the syntax used in a normal ASP.NET Web Forms page. The Velocity Template Language was designed specifically for building HTML pages. Velocity provides you with a very clean syntax for performing common operations such as iterating over a set of database records and displaying each record in an HTML page (think Domain Specific Language for HTML).

Configuring nVelocity for ASP.NET MVC

It took me quite a bit of time to figure out how to get nVelocity configured to work with ASP.NET MVC. The problem is that you must grab files from two different projects to get everything to work (and some of the assemblies are hiding in nested folders).

Here are the steps that I followed to get nVelocity to work:

Step 1:

Download and unzip the MvcContrib binaries from the following website:

http://www.CodePlex.com/MvcContrib

Step 2:

Download and unzip the Castle Project from the following website:

http://www.castleproject.org/castle/download.html

Step 3:

After you unzip the archive from step 2, navigate to the bin folder and unzip the external-dependencies.zip archive. This archive contains the nVelocity.dll assembly.

Step 4:

Create a new Visual Studio 2008 ASP.NET MVC Application

Step 5:

Add a reference to the MvcContrib.Castle assembly which you can find in the archive that you downloaded in Step 1 (The MvcContrib.Castle assembly is part of the MvcContrib project and not the Castle Project).

Step 6

Add a reference to the NVelocity assembly which you unzipped in Step 3.

Two big warnings. First, don’t use the nVelocity assembly located at http://nvelocity.sourceforge.net. If you do a search for nVelocity with a search engine, this is the first entry that appears. Unfortunately, this project has not been updated since 2003 and the nVelocity assembly is massively out of date. Use the nVelocity assembly from the Castle Project instead.

Second, make sure that you Unblock any files that you download before you unzip them. You can unblock a file by right-clicking the file, selecting Properties, and clicking the Unblock button. If you fail to unblock an archive, then you will encounter security issues when you attempt to use files from the archive within Visual Studio.

Using the nVelocity View Engine

After you complete the steps in the previous section, you are ready to start using the nVelocity view engine. There are two ways that you can indicate to the ASP.NET MVC framework that you want to use nVelocity instead of the normal Web Forms view engine.

First, you can modify a controller’s ViewEngine property within a controller action before returning a view. For example, the HomeController in Listing 1 uses nVelocity for its Index() action.

Listing 1 – HomeController.vb (VB.NET)

Imports System.Web.Mvc
 
Namespace Tip19.Controllers
    Public Class HomeController
        Inherits Controller
 
        Private _dataContext As New MovieDataContext()
 
        Public Function Index() As ActionResult
            Me.ViewEngine = New MvcContrib.Castle.NVelocityViewFactory()
 
            Return View(_dataContext.Movies)
        End Function
 
    End Class
End Namespace

Listing 1 – HomeController.cs (C#)

using System.Web.Mvc;
using Tip19.Models;
 
namespace Tip19.Controllers
{
    public class HomeController : Controller
    {
        private MovieDataContext _dataContext = new MovieDataContext();
 
        public ActionResult Index()
        {
            this.ViewEngine = new MvcContrib.Castle.NVelocityViewFactory();
 
            return View(_dataContext.Movies);
        }
 
    }
}

If you want to use nVelocity for only certain pages within your web application, then setting the ViewEngine property is an easy way to switch view engines. However, if you want to use nVelocity for all of your views, then you should consider creating a custom Controller Factory. The custom Controller Factory in Listing 2 changes the default view engine to nVelocity.

Listing 2 – VelocityControllerFactory.vb (VB.NET)

Imports System
Imports System.Web.Mvc
 
Public Class VelocityControllerFactory
    Inherits DefaultControllerFactory
 
    Protected Overrides Function GetControllerInstance(ByVal controllerType As Type) As IController
        Dim controller As IController = MyBase.GetControllerInstance(controllerType)
        Dim velocityController As Controller = TryCast(controller, Controller)
        If velocityController IsNot Nothing Then
            Dim context = New ControllerContext(Me.RequestContext, velocityController)
            velocityController.ViewEngine = New MvcContrib.Castle.NVelocityViewFactory()
        End If
        Return controller
    End Function
 
End Class

Listing 2 – VelocityControllerFactory.cs (C#)

using System;
using System.Web.Mvc;
 
namespace Tip19.Controllers 
{ 
    public class VelocityControllerFactory : DefaultControllerFactory 
    { 
        protected override IController GetControllerInstance(Type controllerType) 
        { 
            IController controller = base.GetControllerInstance(controllerType); 
            Controller velocityController = controller as Controller;
            if (velocityController != null) 
            {
                var context = new ControllerContext(this.RequestContext, velocityController);
                velocityController.ViewEngine = new MvcContrib.Castle.NVelocityViewFactory();
            } 
            return controller; 
        } 
    } 
}

In order to use a custom Controller Factory, you must register the factory within your application’s Global.asax file. The modified Global.asax file in Listing 3 contains a call to the SetControllerFactory() method within its Application_Start() method.

Listing 3 – Global.asax.vb (VB.NET)

Imports Tip19
 
Public Class GlobalApplication
    Inherits System.Web.HttpApplication
 
    Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
 
        ' MapRoute takes the following parameters, in order:
        ' (1) Route name
        ' (2) URL with parameters
        ' (3) Parameter defaults
        routes.MapRoute( _
            "Default", _
            "{controller}/{action}/{id}", _
            New With {.controller = "Home", .action = "Index", .id = ""} _
        )
 
    End Sub
 
    Sub Application_Start()
        ControllerBuilder.Current.SetControllerFactory(GetType(VelocityControllerFactory))
        RegisterRoutes(RouteTable.Routes)
    End Sub
End Class

Listing 3 – Global.asax.cs (C#)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Tip19.Controllers;
 
namespace Tip19
{
    public class GlobalApplication : System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 
            routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            );
 
        }
 
        protected void Application_Start()
        {
            ControllerBuilder.Current.SetControllerFactory(typeof(VelocityControllerFactory));
            RegisterRoutes(RouteTable.Routes);
        }
    }
}

After you register the VelocityControllerFactory, all controllers in your MVC application will use the nVelocity view engine by default. You no longer need to modify the ViewEngine property within each and every controller action method.

Creating an nVelocity View

You create an nVelocity view by creating a .vm file. Visual Studio does not contain a template for Velocity views. You can create a Velocity view by creating an HTML page and changing its extension from .htm to .vm.

For example, the view in Listing 4 contains a Velocity template that displays all of the movies passed from the HomeController from Listing 1.

Listing 4 – Views\Home\Index.vm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" >
 
<head>
 
<title>Untitled Page</title>
 
</head>
 
<body>
 
#foreach( $movie in $Viewdata.Model )
 
<li><a href="/Home/Edit/$movie.Id">$movie.Title</a></li>
 
#end
 
</body>
 
</html>
 

The view in Listing 4 takes advantage of the Velocity template language to display the movies. Notice that a for…each block is created by using the Velocity directives #foreach and #end. Notice that you use a $ to mark something as a variable. Therefore, you can refer to ViewData.Model with the expression $Viewdata.Model. Velocity is not case-sensitive.

There is a complete reference to the Velocity language located at the Apache Software Foundation website. This website also has a quick guide to Velocity. See:

http://velocity.apache.org/engine/releases/velocity-1.5/vtl-reference-guide.html

http://velocity.apache.org/engine/releases/velocity-1.5/user-guide.html

Summary

In this tip, I demonstrated how you can use the nVelocity template engine with an ASP.NET MVC application. I showed two methods of swapping out the default Web Forms view engine. I showed how you can specify a particular view engine for a particular controller action and I showed how you can specify a particular view engine for all controller actions.

I’m certainly not recommending that you should abandon the Web Forms view engine in favor of the nVelocity view engine. The real goal of this tip was to demonstrate the flexibility of ASP.NET MVC. If you don’t like anything about the ASP.NET MVC framework, you always have the option of changing it.

Download the Code

4 Comments

  • Great job Stephen. I always like the way you explain things.

    Keep it coming!!!

    Yash

  • Stephen, this blog put me on the trail to a proper implementation of an XSLT view-engine. But when building that, I run into a problem I also notice in your nVelocity sample: you hard-code the paths in your links (like "/Home/Edit/$movie.Id"). What HtmlHelper.ActionLink-like solution could you think of to generate this kind of links in nVelocity or XSLT?

  • @Richard - Great question! The MvcContrib project includes an NVelocityHtmlHelper class that includes helper methods for NVelocity. Realize that an HTML Helper method is just a method that returns a string (a helper method injects a string into a page). So, you could create custom helpers pretty easily -- see my ASP.NET MVC Tip #1 - Create New HTML Helpers with Extension Methods at: http://weblogs.asp.net/stephenwalther/archive/2008/06/13/asp-net-mvc-tip-1-creating-new-html-helpers-with-extension-methods.aspx

  • Please provide the clear steps for use the nvelocity view engine.
    I have done the first two steps what you described.
    So give the clear steps to follow.

Comments have been disabled for this content.