Hi, Habr! I noticed that there was somehow undeservedly avoided such a wonderful MVC framework for .NET as Monorail. Therefore, in fact, I will try to fill this gap. For a start, it makes sense to touch on the basics: creating a project template and the simplest example in order to see how it all works.
So let's go! I just want to warn you that this is my first article and therefore some flaws are quite acceptable. I am pleased to hear constructive criticism.
Download binary files here:
sourceforge.net/projects/castleproject/files/MonoRail/2.0/Castle.MonoRail-2.0.0.zip/downloadNaturally, you do not need all the dll that are in the archive, we take only the most necessary.
Creating a project.
There are two ways to create an initial project that is ready to write code directly: using the VS template and the pens themselves.
')
The first method, as far as I know, lost its relevance after the Castle project ceased to be distributed as a separate MSI file. Now you can use the template, but links to assemblies will still have to be interrupted on your way to them. Just in case, here is a link to a ready-made test project template for VS2008:
tech.wowkhmer.com/wp-content/uploads/2008/11/CastleMonoRailProject.zip . True, I can not guarantee that it is fully working, as I myself do not use templates for Monorail.
Because of the foregoing, let us dwell on the creation of the project in the second way.
Step 1. Create a new ASP.NET application.
In this empty project, we don’t need a Default.aspx. But do not rush to remove it. In order to enter into the browser line
www.mysite.com we were successfully redirected to our main page mysite.com/home/index.rails, this file is still useful to us. Designer and .cs files will be deleted, and default.aspx itself will be brought somewhere to this form:
<%@ Page Language="C#" %> <script runat="server"> protected override void OnLoad(EventArgs e) { Response.Redirect("~/home/index.rails"); base.OnLoad(e); } </script> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Welcome</title> </head> <body> <p> If you were not redirected, please <a href="home/index.rails">click here</a>. </p> </body> </html>
<%@ Page Language="C#" %> <script runat="server"> protected override void OnLoad(EventArgs e) { Response.Redirect("~/home/index.rails"); base.OnLoad(e); } </script> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Welcome</title> </head> <body> <p> If you were not redirected, please <a href="home/index.rails">click here</a>. </p> </body> </html>
Here home / index.rails is actually the path to the main page of the site. Naturally, the resolution of the rails can be changed, but in the examples I will use it.
Step 2. Configuration
Add the following assembly of the downloaded us:
- Castle.Core
- Castle.Monorail.Framework
- Castle.Monorail.Framework.Views.NVelocity
We will use NVelocity as an engine for rendering presentations, although there are no restrictions on this in Monorail and, moreover, other engines, such as Brail, for example, are shipped with it. I worked with Brail and NVelocity, but I liked the second one more, besides Brail at that time had rather weak support and many things were not implemented. How things are now I do not know, but I will be glad to hear.
We make changes to web.config. In my project it turned out something like this:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <configSections> <section name="monorail" type="Castle.MonoRail.Framework.Configuration.MonoRailSectionHandler, Castle.MonoRail.Framework" /> </configSections> <monorail> <controllers> <assembly>TestMonorailApp</assembly> </controllers> <viewEngines viewPathRoot="Views"> <add type="Castle.MonoRail.Framework.Views.NVelocity.NVelocityViewEngine, Castle.MonoRail.Framework.Views.NVelocity" /> </viewEngines> </monorail> <system.web> <compilation debug="true" /> <httpHandlers> <add verb="*" path="*.rails" type="Castle.MonoRail.Framework.MonoRailHttpHandlerFactory, Castle.MonoRail.Framework" /> <add verb="*" path="*.vm" type="System.Web.HttpForbiddenHandler" /> </httpHandlers> </system.web> </configuration>
<?xml version="1.0" encoding="UTF-8"?> <configuration> <configSections> <section name="monorail" type="Castle.MonoRail.Framework.Configuration.MonoRailSectionHandler, Castle.MonoRail.Framework" /> </configSections> <monorail> <controllers> <assembly>TestMonorailApp</assembly> </controllers> <viewEngines viewPathRoot="Views"> <add type="Castle.MonoRail.Framework.Views.NVelocity.NVelocityViewEngine, Castle.MonoRail.Framework.Views.NVelocity" /> </viewEngines> </monorail> <system.web> <compilation debug="true" /> <httpHandlers> <add verb="*" path="*.rails" type="Castle.MonoRail.Framework.MonoRailHttpHandlerFactory, Castle.MonoRail.Framework" /> <add verb="*" path="*.vm" type="System.Web.HttpForbiddenHandler" /> </httpHandlers> </system.web> </configuration>
First is the registration section of the monorail. In it we indicate where you need to load controllers for our application. Since my example is simple, the controllers are in the same assembly and its name is indicated accordingly. Further in the same section we register our rendering engine and specify the root for the tree of the catalog of views (in our case it is “Views”). And lastly, we add a handler to the selected extension (rails) and deny access to vm files (this extension is used for NVelocity templates and we have nothing to access from outside).
Step 3. It remains only to create a folder structure.
I have it as shown in the picture.

Done, the project template has been created!
Adding the simplest functionality
We created a project, but what a pleasure from it, if nothing else works?
Let's create a controller that, for example, will display a list of books.
For this we need the Book model, which we put in the Models folder. Naturally, in real projects, models will be in separate assemblies, but not in our simple example. Here is the implementation of the Book class:
public class Book { public String Title { get; set; } public String Author { get; set; } public static IList<Book> FindAll() { return new List<Book> { new Book { Title = "Alice in Wonderland", Author = "Lewis Carroll" }, new Book { Title = "Pinocchio", Author = "Carlo Collodi" }, new Book { Title = "I, Robot", Author = "Isaac Asimov" } }; } }
public class Book { public String Title { get; set; } public String Author { get; set; } public static IList<Book> FindAll() { return new List<Book> { new Book { Title = "Alice in Wonderland", Author = "Lewis Carroll" }, new Book { Title = "Pinocchio", Author = "Carlo Collodi" }, new Book { Title = "I, Robot", Author = "Isaac Asimov" } }; } }
The FindAll method simply returns to us a collection of three books that we will use in our test case.
Now create the controller. Since we in deafult.aspx have specified the default path as home / index.rails, we will place a list of our books on this page.
In the Controllers folder, create the HomeController, which is inherited from SmartDispatcherController, which is part of Monorail. Strictly speaking, in our example, you can also inherit from Controller, because we will not use binders in our example, but in real projects, the SmartDispatcherController functionality is very often still in demand.
There we create the Index method, which will be called when typed in the browser mysite.com/home/index.rails. The class implementation has the following form:
public class HomeController : SmartDispatcherController { public void Index() { PropertyBag["books"] = Book.FindAll(); } }
public class HomeController : SmartDispatcherController { public void Index() { PropertyBag["books"] = Book.FindAll(); } }
Here we just simply load all the books into the container available in View. This is quite consistent with the spirit of the skinny controller / fat model, when all the logic is in the model, and the controller is only responsible for transferring data between the view and the model.
It remains to create the actual html code. We will place it in the view folder and the subfolder home. Thus, we delimit views depending on the controller to which they belong. There we create an index.vm file containing the following:
<!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>Test Application</title> </head> <body> <h3>List of books:</h3> #foreach($book in $books) #each <li> $book.Title by $book.Author </li> #beforeall <ul> #afterall </ul> #end </body>
<!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>Test Application</title> </head> <body> <h3>List of books:</h3> #foreach($book in $books) #each <li> $book.Title by $book.Author </li> #beforeall <ul> #afterall </ul> #end </body>
Here we use the foreach macro to walk through our books collection. It is available here as a regular variable. That is, everything that we write in the PropertyBag in the controller becomes variable in the view. Otherwise, this file is a regular html.
Here is your first simplest example on Monorail and is ready.
Now you need to run it. If you added this project as a virtual directory in IIS, then by default it naturally does not know how to work with the .rails resolution. To teach him how to do this, simply add the standard aspnet_isapi.dll to the mappings for .rails permission. The path to it can be viewed, for example, in the same mapping for .aspx files. The main thing is not to get rid of the Check that file exists checkbox when adding a mapping, because physically your .rails files do not exist, and IIS will try to find them.

I think that's enough for a start. Of course, this article does not have many useful features, such as:
- Work with the database
- Automatic binding of data from the request to the controller
- Validations
- Routs
- Templates, Helper, Components for presentation
- And much more...
Write about everything now, I do not see any sense. But if the topic is interesting to you, then I am ready to continue writing articles about this wonderful framework, where all the above points will be touched upon in more detail.
Link to Castle project -
www.castleproject.org