NVelocity Documentation

This is a copy of the documentation at CastleProject . For the moment the last place where NVelocity is maintained.
The copy is to ensure that the documentation is not lost in time.

Introduction

Contents

The NVelocity View Engine uses NVelocity.

NVelocity is a port of the excellent Apache Jakarta Velocity project. It is a very simple, easy to learn and extensible template engine. Due to the lack of releases, support and bug fixes on the original port, the Castle Team decided to fork the project, bringing it to our code repository, fixing the bugs and improving it with more features.

The first thing you need to read about NVelocity is not even on this web site. You can find on the original Velocity web site

Frequently Asked Questions on NVelocity View Engine can be found on the standard MonoRail FAQ

To use NVelocity View Engine inform the type on the customEngine on the configuration file:

1<viewEngine
2    viewPathRoot="views" 
3    customEngine="Castle.MonoRail.Framework.Views.NVelocity.NVelocityViewEngine, Castle.MonoRail.Framework.Views.NVelocity" />

NVelocity files

NVelocity uses the extension .vm so just create your views with that extension. Remember that from your controller you should not reference file extensions when defining views to render.

Layouts

Use the $childContent context variable to render the content of the view on the layout template. The following is a simple layout using NVelocity:

1<html>
2Welcome
3
4$childContent
5
6Footer
7</html>

Order of execution
The view template selected by the controller is executed before the layout template. In fact the layout template is merged with the result of the view template execution.

Configuration

The NVelocity View Engine looks for a file nvelocity.properties in the root of the view folder. You can use this file to configure how NVelocity should behave.

For example, to configure NVelocity to support Chinese encoding create a text file named nvelocity.properties, save it to your views folder and add the following content:

1input.encoding=GB2312
2output.encoding=GB2312

More information on the entries can be found on the original Velocity documentation.

Macros

NVelocity supports macros, but keep in mind that they have problems. If you want to use macros you can create a folder macros under your views root folder.

All .vm files in this folder will be loaded as a NVelocity Macro library so the macros will be available to all templates.

Fancy foreach Loops

Inspired on FrogCreek's fancy loops. The following code should be self-explanatory:

 1#foreach($i in $items)
 2#each (this is optional since it's the default section)
 3       text which appears for each item
 4#before
 5       text which appears before each item
 6#after
 7       text which appears after each item
 8#between
 9       text which appears between each two items
10#odd
11       text which appears for every other item, including the first
12#even
13       text which appears for every other item, starting with the second
14#nodata
15       Content rendered if $items evaluated to null or empty
16#beforeall
17       text which appears before the loop, only if there are items
18       matching condition
19#afterall
20       text which appears after the loop, only of there are items
21       matching condition
22#end

All sections are optional, and they can appear in any order multiple times (sections with same name will have their content appended). So for example you can use it to create table contents with alternating styles:

 1#foreach($person in $people)
 2#beforeall
 3       <table>
 4               <tr>
 5               <th>Name</th>
 6               <th>Age</th>
 7               </tr>
 8#before
 9       <tr
10#odd
11       Style='color:gray'>
12#even
13       Style='color:white'>
14
15#each
16       <td>$person.Name</td>
17       <td>$person.Age</td>
18
19#after
20       </tr>
21
22#between
23       <tr><td colspan='2'>$person.bio</td></tr>
24
25#afterall
26       </table>
27
28#nodata
29       Sorry No Person Found
30#end
31

Which will output something like:

 1<table>
 2       <tr>
 3       <th>Name</th>
 4       <th>Age</th>
 5       </tr>
 6       <tr style='color:white'>
 7               <td>John</td>
 8               <td>32</td>
 9       </tr>
10       <tr><td colspan='2'>Monorail programmer</td></tr>
11       <tr style='color:gray'>
12               <td>Jin</td>
13               <td>12</td>
14       </tr>
15       <tr><td colspan='2'>Castle guru</td></tr>
16</table>

If the $people variable was null the output will be:

1Sorry No Person Found

NVelocityViewEngine Variables

The NVelocityViewEngine is responsible for making "useful" variables available to your view. Here's the list of variables added to the context by the NVelocityViewEngine:

Context Variable Description
$controller The controller being executed.
$context The IRailsEngineContext.
$request context.Request
$response context.Response
$session context.Session
$childContent Used inside Layouts. It defines the content rendered by a View.
$page Available in *.njs views and is added in the GenerateJS method.
$siteroot context.ApplicationPath

Additionally - the contents of the following collections are merged into the context:

  • controller.Resources
  • context.Params
  • controller.Helpers
  • context.Flash
  • controller.PropertyBag

Each key in each of the collections becomes a $variable. For example:

 1class MyController
 2{
 3    public void Index()
 4    {
 5       PropertyBag["myvariable"] = "some value";
 6       Context.Params["othervariable"] = "some other value value";
 7       Context.Flash["anothervariable"] = "yet one more";
 8    }
 9}
In your view you will have the following variables:
  • myvariable
  • othervariable
  • anothervariable

Helpers are also added to allow you to invoke static members on some common types:

  • Byte
  • SByte
  • Int16
  • Int32
  • Int64
  • UInt16
  • UInt32
  • UInt64
  • Single
  • Double
  • Boolean
  • Char
  • Decimal
  • String
  • Guid
  • DateTime

This allows you to do useful things like:

1The Current time is: $DateTime.Now

Accessing the PropertyBag¶
If you want to list the variables in the property bag - then add a reference to the PropertyBag:

1class MyController
2{
3    public void Index()
4    {
5        PropertyBag["PropertyBag"] = PropertyBag;
6    }
7}

then in your view $PropertyBag is what you want:

 1Property bag variables
 2#foreach($key in $PropertyBag)
 3#beforeall
 4
 5    Name
 6    value
 7
 8#each
 9
10    $key
11    $PropertyBag.get_Item($key)
12
13#afterall
14
15#end

ViewComponent Support

NVelocity allows you to create your own directives, so that's how we introduced components to it. Basically you can use:

  • For inline components:
    1#component(ComponentName)
  • For components with body content (aka block components):
    1#blockcomponent(ComponentName)
    2  some content
    3#end
    

ViewComponents have access to the IRailsContext so you can access form parameters, session, etc. Sometimes however it's important to specify some parameters.

Passing Parameters in a Dictionary

Use the name of the component followed by a dictionary string.

1#component(MyFirstComponent "%{firstParam='some value',anotherParam='other value'}")

You can then access the parameters from the component code:

 1public class MyFirstComponent: ViewComponent
 2{
 3    public override void Render()
 4    {
 5        object param1 = Context.ComponentParameters["firstParam"];
 6        object param2 = Context.ComponentParameters["anotherParam"];
 7
 8        ...
 9    }
10}

Key/Value Pairs

In this case you need to use the keyword with followed by a sequence of key/value pairs:

1#component(ComponentName with "name=john" "address=some address")

You're free to use interpolation as well

1#component(ComponentName with "name=${customer.name}")

You can gain access to the component parameters using the Context.ComponentParameters too.

Data Type Handling

Every data type is supported. However literal values will be automatically converted to text. If you want to specify a different type, create a varible on NVelocity or use some structure data available on the view.

The parameter value below will be converted to string

1#component(ComponentName with "age=1")

The parameter value below will remain an Int32

1#set($age = 27)
2#component(ComponentName with "age=${age}")

A Simple Example

The view snippet:

1#blockcomponent(SecurityComponent with "role=admin")
2  this will only be rendered if the current user is in the specified role
3#end

The component code:

 1   
 2using Castle.MonoRail.Framework;
 3
 4namespace WebApp
 5{
 6    public class SecurityComponent : ViewComponent
 7    {
 8        bool shouldRender;
 9
10        public override void Initialize()
11        {
12            String role = ComponentParameter["role"] as String;
13            shouldRender = RailsContext.User.IsInRole( role );
14        }
15
16        public override void Render()
17        {
18            if (shouldRender) Context.RenderBody();
19        }
20    }
21}