So I made it to Part 3. Who knew I had it in me?

For the uninitiated, I'm braindumping on my meanderings through the Timok sample application. I'd advise you to check out part 1 and part 2, partially because Part 2 includes a disclaimer that says, now that I look at it closely, don't listen to me.

So far, we've followed a request through a controller and how to apply filters to controllers. This time, we're finally going to look at some rendered code. When we left off, we had determined that unauthenticated requests to the main page, /home/index.rails, we're redirected to the Index action on the Login controller.

LoginController derives from ControllerBase, rather than SecureController. So it will not run the request through the AuthenticationFilter. Instead, the Index action executes normally. That is, it will use the default layout and the index.vm view.

So are we finally rendering something on the screen yet?

Why, yes, we are. As mentioned in part 1, the default layout will be rendered with the index.vm view in Views/Login. The HTML you see in index.vm is what is rendered on the page. Sort of. We'll take a look at it now.

OK, it kinda looks like HTML but I'm having some acid ASP flashbacks

Yeah, and it's not as pleasant as you would have hoped, right? The HTML you are looking at is littered with escape sequences that mean something to the view parser. Like classic ASP, these are processed server-side and the view engine will render appropriate HTML based on the command and its arguments.

Note that we are using NVelocity as the view engine. It is the default one provided by Monorail but is not the only one. Brail is pretty popular as is ASP.NET web forms, which has a syntax similar to what you are used to in ASP.NET. I have zero experience with either of them so in the immortal words of Handy: Read a book.

In the meantime, just assume that anything with a funky character in front, like # or $, is for NVelocity to figure out. We'll look at a couple of these next.


The text 'twixt this and the #end block will be rendered in the page's <head> tag.


Generates a base URL corresponding to the base application. For example, if your application resides at http://localhost/Timok.Rbr.Portal, this URL will be substituted in place of $siteroot when the page is rendered. It is like using ~ in ASP.NET web forms.

"$UrlHelper.For("%{action='ForgotYourPassword'}")?username=" + $F('username');

This is a busy little bit of code. First is the UrlHelper which is an NVelocity construct that will create a URL for you based on the parameters passed in.In this case, it will build a URL corresponding to the ForgotYourPassword action.

$F isn't actually server-side code. It is rendered as-is in the client. $F is defined in one of MonoRail's js files (AjaxScripts.js). It is a sort of shorthand that says, "append the value of the 'username' form field to this URL when this code is executed. And since we don't know what this will be when the HTML is generated, it has to be a client-side function. It is similar to:


$Form elements

These are for various form-related functions. $Form.FormTag generates the <form> tag in HTML while $Form.EndFormTag generates the </form> (along with some validation code). $Form.LabelFor and $Form.TextField generate <label> and <input type='text'> elements respectively. I'll leave it to you to figure out what $Form.PasswordField does.


This should be somewhat self-explanatory. The HTML in this block is rendered only if the "error" server variable is defined.


We finally got to look at some HTML even if it looked a little funny. I sorta skimmed over the funky NVelocity syntax for a few reasons:

  • It's NVelocity-specific. Brail, ASP.NET WebForms, and other view engines will have their own syntax
  • The idea should be familiar to you if you've done classic ASP development, even if the syntax is different
  • You can view the source of the resulting page just as easily as I can to see what each of these things does

From here, we'll follow through with the form submittal to see what happens when the user actually does log in.

Kyle the Moot