MonoRail peeves

In work, we’ve been using MonoRail for a while. It’s a C#/.NET web application framework, and it’s very much nicer than ASP.NET, which is what I was using before.

Now I’ve had a bit of experience with it, though, there are things I would definitely change: I want the framework to allow me to compose page elements more easily, and to have stronger type-checking.

The easy one first. I’m going to talk about…

Type checking

I like static type checking. I like that C# recently added generic types, because it makes the static typing stronger. More mistakes are caught at compile-time. This is good. It also means that the IDE is able to help you by autocompleting pretty much anything, and allowing you to refactor identifier names really easily.

Type checking is stymied in a couple of places in MonoRail. One is in the fact that views, actions and URLs are referred to by name, passed around as strings. This is annoying, though it’s a fairly manageable problem. (Somebody has hacked together a solution to this*.)

What I am more concerned about though is the rampant dynamic typing within views.

‘Views’ in a MVC framework like MonoRail are templates which take data provided by the controller (the code which handles the action—page request, or form submission), and bungs it into HTML for output. For example, given a collection of ‘customer’ objects, a view might output a table with one line for each customer and two columns, customer name and customer code.

Views are defined using a template language. The default MonoRail template language is Velocity. Others, on MonoRail and other platforms, include StringTemplate, Brail, Haml

…and all of them are dynamically typed. A typical line from a view, written in a templating language might look like:

<tr><td>$cust.Name</td><td>$cust.AccNumbr</td><tr>

At runtime, these names are looked up, and retrieved from (say) the ‘customer’ object which has been passed in.

But what if I have a spelling mistake? It’s not ‘AccNumbr’, it’s ‘AccNumber’. Yeah, yeah, testing should catch it, but I don’t want testing to catch it; I want the compiler to catch it. I also want to be able to take advantage of automatic refactoring to change it to, for example, ‘AccountNumber’ without hunting through every view which refers to it. And I’d like the development environment to be able to save me typing, so I just need to type ‘cust.Acc…’.

Ideally views would:

  1. Be compiled into bytecode† at compile-time, (and the compiler would check type-errors). This implies that each view would…
  2. Declare parameters and declare the types of these parameters. This implies views would…
  3. Essentially be objects which have methods which take parameters and return a result.

Now at this point I expect someone to chime in and say that views have got to be dynamically typed, since they’re fodder for HTML designers, and they’re therefore supposed to be written in a nice, soft, non-static-compilation kind of a language; or that views should be simple, and static type checking isn’t ‘simple’. I don’t buy that. Essentially we’re not changing anything here, except catching a class of bugs earlier. Were not actually making the display logic any more verbose.

Views shouldn’t look too much like programs. They’re performing intentionally simple computations. They’re processing text. The controller should contain the main program logic; the view should only be concerned with display logic.

All we need should need to specify in the way of type information is either the interface which the view implements (which implies the types of the arguments), or else a list of named and typed parameters. Something perhaps a little like this:

// Such-and-such a project
// Main page, shows list of customers

login: User
customers: List<Customer>
message: String

title=Main page for $login.Name

body=<div>
....
</div>

That would be a view with three parameters and two ‘methods’; one method which returns the page title, and one which returns the HTML to be jammed into the body of the page.

The syntax needs a little work. One would need to work out how to accommodate (or work around) importing types from different namespaces. (I’d rather not begin each view with a list of namespace/package imports.) Ideally the system should also accommodate parameters passed implicitly, like MonoRail-style ‘helpers’, or other, common parameters—like the location of the site root—which potentially every view needs.

However I believe that the concept is sound. It would make my life easier.

One final note: in the example above, most templating languages would take the value of login.Name (presumed to be a string), and jam it into the output HTML. This causes a huge class of security issues called XSS vulnerabilities. Any values should be correctly converted or encoded when output. I may have more to say about that.

* It seems that this ‘hack’ is now a public project, the Castle.Contrib.CodeGenerator project. I might start using it…
† I’m working in C# at the moment, hence assuming that you’d compile everything to bytecodes (for Java or .NET).

4 thoughts on “MonoRail peeves

  1. Simon Brooke

    The approach I used to this problem in Jacquard was to output custom XML and then use XSL to apply site-specific styling; in later Jacquard applications I output well-formed but bland XHTML as the ‘custom XML’ so that even without styling it was usable.

    This solution means that all the things which talk to the database and manipulate values were written the same language. The skin language (XSL) had no means of interrogating objects except by requesting further XML fragments from URLs.

    I (obviously) think there’s a lot of merit in this approach. I find Velocity (and, from what I’ve seen of it, Brail) disgusingly hacky.

  2. Gauthier Segay

    You should give a try at aspview, it works as a view compiler with design time support in VS since it use the same syntax as asp.net page templates.

    You will have compile time type checking when compiling your views with standard c# compilation error messages.

    Also, with it’s design time support, you can use intellisense in your views.

    see http://aspview.com for more information

  3. Andrew Post author

    Ah, interesting. Though I must say that I find the < % %> syntax awkward to type and visually messy.

    And, yes, I am a fussy bugger. However, it must be possible to write some kind of plugin for VS which interprets alternate syntaxes…

  4. Pingback: Strongly typed Action references in Microsoft MVC4 | Andrew’s Mental Dribbling

Leave a Reply

Your email address will not be published. Required fields are marked *