<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Castle</title>
        <link>http://ayende.com/Blog/category/489.aspx</link>
        <description>Castle</description>
        <language>en-US</language>
        <copyright>Ayende Rahien</copyright>
        <managingEditor>Ayende@ayende.com</managingEditor>
        <generator>Subtext Version 1.9.3.51</generator>
        <item>
            <title>Donjon - Hammett's Teasing</title>
            <link>http://ayende.com/Blog/archive/2008/01/20/Donjon--Hammetts-Teasing.aspx</link>
            <description>&lt;p&gt;&lt;a href="http://hammett.castleproject.org/"&gt;Hammett&lt;/a&gt; has just posted &lt;a href="http://hammett.castleproject.org/?p=235"&gt;teaser image&lt;/a&gt; on his blog.&lt;/p&gt; &lt;p&gt;Go check it out. I have some idea about how long ago it started, and to get to this point is amazing (and no, I don't have any extra knowledge about what it does otherwise, except maybe free us from OutOfMemoryError s and manual restarts).&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/10009.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2008/01/20/Donjon--Hammetts-Teasing.aspx</guid>
            <pubDate>Sun, 20 Jan 2008 20:08:51 GMT</pubDate>
            <comments>http://ayende.com/Blog/archive/2008/01/20/Donjon--Hammetts-Teasing.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/10009.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Active Record: Mapping Rewriting</title>
            <link>http://ayende.com/Blog/archive/2008/01/11/Active-Record-Mapping-Rewriting.aspx</link>
            <description>&lt;p&gt;One of the really nice things about using the NHibernate / Active Record stack is that there are so many extensions points.&lt;/p&gt; &lt;p&gt;One of the more fun things is the ability to do runtime modifications of the mapping. Here is a simple example:&lt;/p&gt;&lt;pre&gt;ActiveRecordStarter.ModelsCreated+=&lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt;(ActiveRecordModelCollection models, IConfigurationSource source)
{
    &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (ActiveRecordModel model &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; models)
    {
        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(model.Type == &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(User))
        {
            model.ActiveRecordAtt.Table = "&lt;span style="color: #8b0000"&gt;MyUsers&lt;/span&gt;";
        }
    }
};&lt;/pre&gt;
&lt;p&gt;Here we are re-writing the table that the User entity will go to. We can get much more complex, since we have all the knowledge of the structure of the code and can apply things like naming convention, validation, etc. It is also a fast way to translate between database/conventions.&lt;/p&gt;
&lt;p&gt;NHibernate has a similar concept, INamingStrategy, which can be used to some of the same purposes, but I like this approach better, since it gives me more semantic information.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/9997.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2008/01/11/Active-Record-Mapping-Rewriting.aspx</guid>
            <pubDate>Fri, 11 Jan 2008 14:38:37 GMT</pubDate>
            <comments>http://ayende.com/Blog/archive/2008/01/11/Active-Record-Mapping-Rewriting.aspx#feedback</comments>
            <slash:comments>3</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/9997.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Castle Style Errors</title>
            <link>http://ayende.com/Blog/archive/2007/11/05/Castle-Style-Errors.aspx</link>
            <description>&lt;p&gt;I had to compare different styles of error handling approaches, and I automatically compared the ideal, Castle Style errors, to the nasty, Mystery HRESUTL of the Week.&lt;/p&gt; &lt;p&gt;But what does Castle Style errors means?&lt;/p&gt; &lt;p&gt;Let us take a look at a few of them. When an module that was registered before the MonoRail http module had thrown an exception:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Exception(
	"&lt;span style="color: #8b0000"&gt;An exception happened on Global application or on a module that run before MonoRail's module. &lt;/span&gt;" + 
	"&lt;span style="color: #8b0000"&gt;MonoRail will not be initialized and further requests are going to fail. &lt;/span&gt;" + 
	"&lt;span style="color: #8b0000"&gt;Fix the cause of the error reported below.&lt;/span&gt;", context.Context.Error);&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Or what happens when you are trying to access an ActiveRecord class when you didn't initialize it properly?&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;String.Format("&lt;span style="color: #8b0000"&gt;An ActiveRecord class ({0}) was used but the framework seems not &lt;/span&gt;" +
   "&lt;span style="color: #8b0000"&gt;properly initialized. Did you forget about ActiveRecordStarter.Initialize() ?&lt;/span&gt;",
   type.FullName);&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;And:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;String.Format("&lt;span style="color: #8b0000"&gt;You have accessed an ActiveRecord class that wasn't properly initialized. &lt;/span&gt;" +
   "&lt;span style="color: #8b0000"&gt;The only explanation is that the call to ActiveRecordStarter.Initialize() didn't include {0} class&lt;/span&gt;",
   type.FullName);&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;The common theme for those errors is that they are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Descriptive&lt;/li&gt;
&lt;li&gt;Show all the relevant information&lt;/li&gt;
&lt;li&gt;Suggest a probable solution&lt;/li&gt;
&lt;li&gt;Save time&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;I added the following exception:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ActiveRecordException(String.Format(
	"&lt;span style="color: #8b0000"&gt;You can't use [Property] on {0}.{1} because {2} is an active record class, did you mean to use BelongTo?&lt;/span&gt;",
	model.Property.DeclaringType.Name, model.Property.Name, propertyType.FullName));&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;I added that after I spent half an hour trying to figure out why something was wrong. Since then, I &lt;em&gt;keep&lt;/em&gt; running into this exception, and then it is a "slap on the head, replace [Property] with [BelongsTo] and move on". And that is me, who wrote this bloody annoying exception that I am supposed to already know and avoid triggering. I can't imagine how many hours this exception alone has saved, just for my team.&lt;/p&gt;
&lt;p&gt;In fact, when I gave a talk at DevTeach about MonoRail, I have literally built the entire demo by just following the instructions from the exceptions.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;That&lt;/em&gt; is good error handling, and that is what I consider as the standard that you should aspire to. Anything less than that is cause for anger, anxiety and angst. &lt;em&gt;Do &lt;/em&gt;save yourself the ulcer, put in the best errors you can.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/9839.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2007/11/05/Castle-Style-Errors.aspx</guid>
            <pubDate>Sun, 04 Nov 2007 22:06:05 GMT</pubDate>
            <comments>http://ayende.com/Blog/archive/2007/11/05/Castle-Style-Errors.aspx#feedback</comments>
            <slash:comments>10</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/9839.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Model View Action</title>
            <link>http://ayende.com/Blog/archive/2007/10/26/Model-View-Action.aspx</link>
            <description>&lt;p&gt;&lt;a href="http://adamesterline.com/"&gt;Adam&lt;/a&gt; has an &lt;a href="http://adamesterline.com/2007/10/24/ror-based-mvc-web-frameworks-friend-or-foe/"&gt;interesting discussion&lt;/a&gt; here about handling common actions in MonoRail. This has sparked &lt;a href="http://groups.google.com/group/castle-project-devel/browse_thread/thread/976170df54fde8f5"&gt;some discussion&lt;/a&gt; in the MonoRail mailing list. I wanted to take the chance to discuss the idea in more detail here.&lt;/p&gt; &lt;p&gt;Basically, he is talking about doing this:&lt;/p&gt; &lt;blockquote&gt;&lt;/blockquote&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; IndexAction : SmartDispatcherAction
{
   &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; ISearchableRepository repos;
   &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; indexView;

   &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IndexAction(
      ISearchableRepository repos,
      &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; indexView)
   {
      &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.repos = repos;
      &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.indexView = indexView;
   }

   &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Execute(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; name)
   {
      ISearchable item = repos.FindByName(name);
      &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(item == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
      {
         PropertyBag["&lt;span style="color: #8b0000"&gt;UnknownSearchTerm&lt;/span&gt;"] = name;
         RenderView("&lt;span style="color: #8b0000"&gt;common/unknown_quick_search&lt;/span&gt;");
      }

      PropertyBag["&lt;span style="color: #8b0000"&gt;Item&lt;/span&gt;"] = item;
      RenderView(indexView);
   }
}&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;And then registering it with the routing engine like this:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Route("&lt;span style="color: #8b0000"&gt;/products/&amp;lt;name&amp;gt;&lt;/span&gt;",
    &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; IndexAction(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ProductRepository(), "&lt;span style="color: #8b0000"&gt;display_product&lt;/span&gt;"));
&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Route("&lt;span style="color: #8b0000"&gt;/categories/&amp;lt;name&amp;gt;&lt;/span&gt;",
    &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; IndexAction(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; CategoryRepository(), "&lt;span style="color: #8b0000"&gt;display_category&lt;/span&gt;"));&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Now, accessing "/categories/cars" will give you all the items in the cars category.&lt;/p&gt;
&lt;p&gt;On the face of it, it seems like a degenerated controller, no? Why do we need it? We can certainly map more than a single URL to a controller, so can't we solve that problem that way?&lt;/p&gt;
&lt;p&gt;Let us stop for a moment and &lt;em&gt;think&lt;/em&gt; about the MVC model. Where did it come from? From Smalltalk, when GUI was something brand new &amp;amp; sparkling. It is a design pattern for a connected system. In that case, the concept of a controller made a lot of sense.&lt;/p&gt;
&lt;p&gt;But when we are talking about the web? The web is a disconnected world. What is the sense in having a controller there? An Action, or a Command, pattern seems much more logical here, no?&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/5c61484692ec_11757/image_1.png" atomicselection="true"&gt;&lt;img style="margin: 0px 15px 0px 0px" height="244" alt="image" src="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/5c61484692ec_11757/image_thumb_1.png" width="331" align="left" border="0" /&gt; &lt;img style="margin: 0px 0px 0px 15px" height="172" alt="image" src="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/5c61484692ec_11757/image_thumb.png" width="163" align="right" border="0" /&gt;&lt;/a&gt; But then we have things that just doesn't fit this model. Consider the example of CRUD on orders. We can have a controller, which will handle all of the logic for this use case in a single location, or we can have four separate classes, each taking care of a single aspect of the use case.&lt;/p&gt;
&lt;p&gt;Personally, I would rather have the controller to do the work in this scenario, because this way I have all the information in a single place, and I don't need to hunt multiply classes in order to find it.&lt;/p&gt;
&lt;p&gt;But, there are a lot of cases where we &lt;em&gt;do&lt;/em&gt; want to have just this single action to happen, or maybe we want to add some common operations to the controller, without having to get in to crazy inheritance schemes.&lt;/p&gt;
&lt;p&gt;For this, MonoRail supports the idea of &lt;a href="http://hammett.castleproject.org/?p=73"&gt;Dynamic Actions&lt;/a&gt;, which supports seamless attachment of actions to a controller.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://hammett.castleproject.org/?p=73"&gt;Hammett&lt;/a&gt; describe them best:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/5c61484692ec_11757/image_2.png" atomicselection="true"&gt;&lt;img height="161" alt="image" src="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/5c61484692ec_11757/image_thumb_2.png" width="523" align="right" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;DynamicActions offers a way to have an action that is not a method in the controller. This way you can “reuse an action” in several controllers, even among projects, without the need to create a complex controller class hierarchy.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The really interesting part in this is that we have both IDynamicAction and IDynamicActionProvider. This means that we get mixin-like capabilities.&lt;/p&gt;
&lt;p&gt;Dynamic Actions didn't get all the love they probably deserve, we don't have the SmartDispatcherAction (yet), so if we want to use them, we will need to handle with the raw request data, rather than with the usual niceties that MonoRail provides.&lt;/p&gt;
&lt;p&gt;Nevertheless, on a solid base it is easy enough to add.&lt;/p&gt;
&lt;p&gt;Now all we need to solve is the ability to route the requests to the correct action, right? This is notepad code, so it is ugly and not something that I would really use, but it does the job:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ActionRoutingController : Controller
{
	&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt; IDynamicAction CreateDynamicAction();
	
	&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; IDictionary&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;, CreateDynamicAction&amp;gt; Routing 
		= &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;, CreateDynamicAction&amp;gt;();
	
	&lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; InternalSend(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; action, IDictionary actionArgs)
	{
		&lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(Routing.ContainsKey(action) == )
			&lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NoActionFoundException(action);
			
		Routing[action]().Execute(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;);
	}
}&lt;/pre&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;What this means is that you can now do this:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; AddRoutedActions()
{
	AddRoutedAction("&lt;span style="color: #8b0000"&gt;categories&lt;/span&gt;", "&lt;span style="color: #8b0000"&gt;/categories/&amp;lt;name:string&amp;gt;&lt;/span&gt;", &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt; {
		&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;  &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; IndexAction(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; CategoryRepository(), "&lt;span style="color: #8b0000"&gt;display_category&lt;/span&gt;");
	});
	
	AddRoutedAction("&lt;span style="color: #8b0000"&gt;products&lt;/span&gt;", "&lt;span style="color: #8b0000"&gt;/products/&amp;lt;name:string&amp;gt;&lt;/span&gt;", &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt; {
		&lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; IndexAction(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ProductRepository(), "&lt;span style="color: #8b0000"&gt;display_product&lt;/span&gt;");
	});
}

&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; AddRoutedAction(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; action, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; url, CreateDynamicAction actionFactory)
{
	RoutingModuleEx.Engine.Add(
		PatternRule.Build(action, url, &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(ActionRoutingController), action));
    
    ActionRoutingController.Routing.Add(action, actionFactory);
	
}&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;And get basically the same result.&lt;/p&gt;
&lt;p&gt;Again, all of this is notepad code, just doodling away, but it is nice to see that all the building blocks are there.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/9813.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2007/10/26/Model-View-Action.aspx</guid>
            <pubDate>Fri, 26 Oct 2007 21:52:40 GMT</pubDate>
            <comments>http://ayende.com/Blog/archive/2007/10/26/Model-View-Action.aspx#feedback</comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/9813.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Template Controllers</title>
            <link>http://ayende.com/Blog/archive/2007/10/26/Template-Controllers.aspx</link>
            <description>&lt;p&gt;&lt;a href="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/f41cf7d243fa_F68D/image_4.png" atomicselection="true"&gt;&lt;img style="margin: 0px 0px 0px 10px" height="268" alt="image" src="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/f41cf7d243fa_F68D/image_thumb_4.png" width="368" align="right" border="0" /&gt;&lt;/a&gt;Sharing common functionality across controllers is something that I have run into several times in the past. It is basically needing to offer the same functionality across different elements in the application.&lt;/p&gt; &lt;p&gt;Let us take for a moment a search page. In my current application, a search page has to offer rich search functionality for the user, the ability to do pattern matching, so given a certain entity, match all the relevant related entities that can fit this entity. Match all openings for a candidate. Match all candidates for an opening.&lt;/p&gt; &lt;p&gt;&lt;em&gt;That &lt;/em&gt;is unique, mostly, but then we have a lot of boiler plate functionality, which moves from printing, paging, security, saving the query and saving the results, changing the results, exporting to XML, loading saved queries and saved results, etc, etc etc. Those requirements are shared among several &lt;/p&gt; &lt;p&gt;On the right you can see one solution for this problem, the Template Controller pattern. Basically, we concentrated all the common functionality into the Base Specification Controller.&lt;/p&gt; &lt;p&gt;What you can't see is that the declaration of the controller also have the following generic constraints:&lt;/p&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;&lt;a href="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/f41cf7d243fa_F68D/image_6.png" atomicselection="true"&gt;&lt;img style="margin: 0px 0px 0px 15px" height="281" alt="image" src="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/f41cf7d243fa_F68D/image_thumb_6.png" width="332" align="right" border="0" /&gt;&lt;/a&gt; public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; BaseSpecificationController&amp;lt;TSpecification, TEntity&amp;gt; : BaseController
	&lt;font color="#0000ff"&gt;where&lt;/font&gt; TSpecification : BaseSpecification&amp;lt;TEntity&amp;gt;, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt;()
	&lt;font color="#0000ff"&gt;where&lt;/font&gt; TEntity : IIdentifable&lt;/pre&gt;
&lt;p&gt;This means that the base controller can perform most of its actions on the base classes, without needing to specialize just because of the different types.&lt;/p&gt;
&lt;p&gt;Yes, dynamic language would makes things much easier, I know.&lt;/p&gt;
&lt;p&gt;Note that while I am talking about sharing the controller logic here, between several controllers, we can also do the same for the views using shared views. Or not. That is useful if we want to use different UI for the search.&lt;/p&gt;
&lt;p&gt;In fact, given that we need to show a search screen, it is not surprising that we would &lt;em&gt;need&lt;/em&gt; a different UI, and some different behavior for each search controller, to get the data required to specify a search.&lt;/p&gt;
&lt;p&gt;Now that we have the background all set up, let us see what we can do with the concrete search controllers, shall we.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/f41cf7d243fa_F68D/image.png" atomicselection="true"&gt;&lt;img height="348" alt="image" src="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/f41cf7d243fa_F68D/image_thumb.png" width="451" align="right" border="0" /&gt;&lt;/a&gt;You can see the structure of them on the right. The search candidates is doing much more than the search orders, but a lot of the functionality between the two is shared. And more importantly, &lt;em&gt;easily&lt;/em&gt; shared.&lt;/p&gt;
&lt;p&gt;Well, if you define the generics syntax above as easy, at least.&lt;/p&gt;
&lt;p&gt;The main advantage of this approach is that I can literally develop a feature on the candidates controller, and then generalize it to support all the other searches in the application.&lt;/p&gt;
&lt;p&gt;In this scenario, we started with searching for candidates, and after getting the basic structure done, I moved to start working on the search orders.&lt;/p&gt;
&lt;p&gt;At the same time, another guy was implementing all the extra functionality (excel export, sending SMS and emails, etc).&lt;/p&gt;
&lt;p&gt;After we I finished the search order page, we merged and refactored up most of the functionality that we needed in both places.&lt;/p&gt;
&lt;p&gt;This is a good approach if you can utilize inheritance in your favor. But there is a kink, if you want to aggregate functionality from several sources, then you are going to go back to delegation or duplication.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://adamesterline.com/"&gt;Adam&lt;/a&gt; has &lt;a href="http://adamesterline.com/2007/10/24/ror-based-mvc-web-frameworks-friend-or-foe/"&gt;interesting discussion&lt;/a&gt; about this issue, and an interesting proposition. But that will be another post.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/9810.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2007/10/26/Template-Controllers.aspx</guid>
            <pubDate>Fri, 26 Oct 2007 18:44:54 GMT</pubDate>
            <comments>http://ayende.com/Blog/archive/2007/10/26/Template-Controllers.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/9810.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Trusting the benchmark</title>
            <link>http://ayende.com/Blog/archive/2007/10/16/Trusting-the-benchmark.aspx</link>
            <description>&lt;p&gt;&lt;a href="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/Whybenchmarkslies_13C01/image.png" atomicselection="true"&gt;&lt;img alt="image" src="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/Whybenchmarkslies_13C01/image_thumb.png" align="right" border="0" /&gt;&lt;/a&gt;I was scanning &lt;a href="http://www.codeproject.com/cs/library/LinFuPart1.asp"&gt;this article&lt;/a&gt; when I read noticed this bit.  A benchmark showing superior performance to another dynamic proxy implementation.  &lt;/p&gt; &lt;p&gt;I should mention in advance that I am impressed. I have built one from scratch, and am an active member of DP2 (and DP1, when it was relevant). That is not something that you approach easily. It is hard, &lt;em&gt;damn&lt;/em&gt; hard. And the edge cases will &lt;em&gt;kill&lt;/em&gt; you there.&lt;/p&gt; &lt;p&gt;But there are two problems that I have with this benchmark. They are mostly universal for benchmarks, actually.&lt;/p&gt; &lt;p&gt;First, it tests unrealistic scenario, you &lt;em&gt;never &lt;/em&gt;use a proxy generation framework with the caching off. Well, not unless you want out of memory exceptions. &lt;/p&gt; &lt;p&gt;Second, it tests the wrong thing. DP2 focus is not on generation efficiency (it is important, but not the main focus), the main focus are correctness (DP2 produces &lt;em&gt;verifiable &lt;/em&gt;code) and &lt;em&gt;runtime&lt;/em&gt; performance. You only generate a proxy type once, this means that if you can do more in the generation phase to make it run faster at runtime, you do it.&lt;/p&gt; &lt;p&gt;Again, it is entirely possible that the LinFu proxies are faster at runtime as well, but I have no idea, and I don't mean to test those. Benchmarks are meaningless most of the time, you need to test for performance yourself.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/9784.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2007/10/16/Trusting-the-benchmark.aspx</guid>
            <pubDate>Tue, 16 Oct 2007 20:39:38 GMT</pubDate>
            <comments>http://ayende.com/Blog/archive/2007/10/16/Trusting-the-benchmark.aspx#feedback</comments>
            <slash:comments>5</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/9784.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Commercial support for Castle Windsor, Castle MonoRail, NHibernate, etc</title>
            <link>http://ayende.com/Blog/archive/2007/10/15/Commercial-support-for-Castle-Windsor-Castle-MonoRail--NHibernate-etc.aspx</link>
            <description>&lt;p&gt;This &lt;a href="http://www.flux88.com/CommentView,guid,868747a3-795f-4bbf-9fa3-80cf85782527.aspx#commentstart"&gt;post&lt;/a&gt; by &lt;a href="http://www.flux88.com/"&gt;Ben Scheirman&lt;/a&gt; is interesting. He points out that the MS.MVC stuff is targeted toward a different crowd than the one who is using MonoRail, it is targeted toward the corporate developers and the All-Microsoft Shops.&lt;/p&gt;
&lt;p&gt;The question of support has been raised again, and it prompted this post. It seems that there isn't a lot of awareness that there &lt;em&gt;are&lt;/em&gt; commercial support options for those tools.&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://www.castlestronghold.com/home/index"&gt;Castle Stronghold&lt;/a&gt; is the obvious place for commercial support for Castle.  &lt;/li&gt;
    &lt;li&gt;&lt;a href="http://labs.jboss.com/" style="text-decoration: line-through;"&gt;JBoss / RedHat&lt;/a&gt;&lt;span style="text-decoration: line-through;"&gt; are offering commercial support for NHibernate.&lt;/span&gt; JBoss no longer support NHibernate.  &lt;/li&gt;
    &lt;li&gt;&lt;a href="http://www.we-can.co.il/Heb/default.aspx"&gt;We!&lt;/a&gt;* (Hebrew site) is offering commercial support for NHibernate and Castle. &lt;/li&gt;
    &lt;li&gt;&lt;a href="http://www.mindscape.co.nz"&gt;Mindscape&lt;/a&gt; is offering commercial support for Castle.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I am actually not very interested in getting support for those, so it is entirely possible (and likely) that I missed some. Most of the active members of the community are members of consultancies that are capable offering support, but those are the one that I am aware of.&lt;/p&gt;
&lt;p&gt;* Full disclosure: I work there.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/9779.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2007/10/15/Commercial-support-for-Castle-Windsor-Castle-MonoRail--NHibernate-etc.aspx</guid>
            <pubDate>Mon, 15 Oct 2007 20:43:26 GMT</pubDate>
            <comments>http://ayende.com/Blog/archive/2007/10/15/Commercial-support-for-Castle-Windsor-Castle-MonoRail--NHibernate-etc.aspx#feedback</comments>
            <slash:comments>5</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/9779.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Multiple parents in Cascading Drop Downs in MonoRail</title>
            <link>http://ayende.com/Blog/archive/2007/10/08/Multiply-parents-in-Cascading-Drop-Downs-in-MonoRail.aspx</link>
            <description>&lt;p&gt;Apparently I am suffering from the Bug Duplication Syndrom. Shortly after posting about &lt;a href="Cascading Drop Downs in MonoRail"&gt;cascading drop downs&lt;/a&gt; in MonoRail, I realized that I have actually duplicated a bug that I have run into while using the cascading drop down extender in the ASP.Net Ajax toolkit. That is not a fixable bug, btw, and has to do with what happens when you have more than a single parent. You can see my post about this scenario &lt;a href="http://www.ayende.com/Blog/archive/2007/04/22/Multiple-Cascading-Drop-Down-Lists.aspx"&gt;here&lt;/a&gt;, but be aware that the solution in that post is vulnerable to race conditions, and I have finally declared that unpracticle to use.&lt;/p&gt; &lt;p&gt;At any rate, I have duplicate the inability to have multiply parents in my &lt;a href="http://www.ayende.com/Blog/archive/2007/10/08/Cascading-Drop-Downs-in-MonoRail.aspx"&gt;previous solution&lt;/a&gt; using MonoRail. And I decided that instead of fixing it in place, I'll show the steps neccesary to fix the problem. Basically, we want to update both the secondaries select and the tertiaries select, which means that our GetSecondaryProfressionsByPrimary.brailjs will now contains:&lt;/p&gt; &lt;blockquote&gt;&lt;/blockquote&gt; &lt;blockquote&gt; &lt;p&gt;page.Replace( 'secondaries', &lt;br /&gt;    Form.Select('secondaries',SecondaryProfessions, &lt;br /&gt;        {@value: @Id, @text: @Name, @firstoption: res.Select})            &lt;br /&gt;)&lt;br /&gt;page.Replace( 'tertiaries', &lt;br /&gt;    Form.Select('tertiaries',TertiaryProfessions, &lt;br /&gt;        {@value: @Id, @text: @Name, @firstoption: res.Select})            &lt;br /&gt;)&lt;br /&gt;page.Call( @hookSecondariesChangeEvent );&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;And that the GetSecondaryProfressionsByPrimary action is now:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; GetSecondaryProfressionsByPrimary(Guid id)
{
	PropertyBag["&lt;span style="color: #8b0000"&gt;SecondaryProfessions&lt;/span&gt;"] =
		professionRepository.FindSecondariesByPrimaryIdOrAll(id);
	PropertyBag["&lt;span style="color: #8b0000"&gt;TertiaryProfessions&lt;/span&gt;"] =
		professionRepository.FindTertiariesByPrimaryIdOrAll(id);
}
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Oh, and that was &lt;em&gt;it.&lt;/em&gt;&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/9753.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2007/10/08/Multiply-parents-in-Cascading-Drop-Downs-in-MonoRail.aspx</guid>
            <pubDate>Mon, 08 Oct 2007 12:39:45 GMT</pubDate>
            <comments>http://ayende.com/Blog/archive/2007/10/08/Multiply-parents-in-Cascading-Drop-Downs-in-MonoRail.aspx#feedback</comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/9753.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Cascading Drop Downs in MonoRail</title>
            <link>http://ayende.com/Blog/archive/2007/10/08/Cascading-Drop-Downs-in-MonoRail.aspx</link>
            <description>&lt;p&gt;I just had this need, and I decided to explore what I could do without referring to what other people has already done. There are probably better ways, but this one has tickled my fancy.&lt;/p&gt; &lt;p&gt;Anyway, the idea here is to display three levels of hierarchy in a profression. Here is the HTML:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;table&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
	&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;tr&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
		&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
			${res.PrimaryProfession}
		&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
		&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
			${Form.Select("primaries",PrimaryProfessions, &lt;br /&gt;                                {@value: @Id, @text: @Name, @firstoption: res.Select}) }
		&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
		&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
			${res.SecondaryProfession}
		&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
		&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
			${Form.Select("secondaries",SecondaryProfessions, &lt;br /&gt;                                 {@value: @Id, @text: @Name, @firstoption: res.Select}) }
		&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
		&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
			${res.TertiaryProfession}
		&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
		&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
			${Form.Select("tertiaries",TertiaryProfessions, &lt;br /&gt;                                 {@value: @Id, @text: @Name, @firstoption: res.Select}) }
		&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;td&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
	&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;tr&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;table&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;This is not very fancy, and the CSS guys would be all over me for using a table, but let us leave that aside. Basically, we render three select elements. Now, let us see the server side, shall we?&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Index()
{
	PropertyBag["&lt;span style="color: #8b0000"&gt;PrimaryProfessions&lt;/span&gt;"] =
		professionRepository.FindAllPrimaries();

	PropertyBag["&lt;span style="color: #8b0000"&gt;SecondaryProfessions&lt;/span&gt;"] =
		professionRepository.FindAllSecondaries();

	PropertyBag["&lt;span style="color: #8b0000"&gt;TertiaryProfessions&lt;/span&gt;"] =
		professionRepository.FindAllTertiaries();
}
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;The ProfressionRepository uses Repository&amp;lt;T&amp;gt; internally, I want to avoid using Repository&amp;lt;T&amp;gt; directly in my controllers. Now, we need to actually respond to change events on the client side:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$j(&lt;span style="color: #0000ff"&gt;document&lt;/span&gt;).ready(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt;()
{
	$j('#primaries').change(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt;()
	{
		$j.ajax({ 
			url:'GetSecondaryProfressionsByPrimary.ashx',
			data: { id: $j('#primaries').val() },
			dataType: 'script'
		});
	});
	hookSecondariesChangeEvent();
});

&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; hookSecondariesChangeEvent()
{
	$j('#secondaries').change(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt;()
	{
		$j.ajax({ 
			url:'GetTertiaryProfressionsBySecondary.ashx',
			data: { id: $j('#secondaries').val() },
			dataType: 'script'
		});
	});
}
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;This is done using jQuery, to hook the events and issue Ajax requests to the server when they are done. Note that I am registering the seconderies change event in a separate function, it will be soon clear why.&lt;/p&gt;
&lt;p&gt;Now, how does the server handles this?&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; GetSecondaryProfressionsByPrimary(Guid id)
{
	PropertyBag["&lt;span style="color: #8b0000"&gt;SecondaryProfessions&lt;/span&gt;"] =
		professionRepository.FindSecondariesByPrimaryIdOrAll(id);
}

&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; GetTertiaryProfressionsBySecondary(Guid id)
{
	PropertyBag["&lt;span style="color: #8b0000"&gt;TertiaryProfessions&lt;/span&gt;"] =
		professionRepository.FindTertiariesBySecondaryIdOrAll(id);
}
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;So we just pass the parameters to the repository, which does all the work for us, in this case, getting the children if the id is valid, or all if it isn't. Now let us move to the relevant views, shall we? We are using BrailJS here, so here is GetSecondaryProfressionsByPrimary.brailjs:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;page.Replace( 'secondaries', 
	Form.Select('secondaries',SecondaryProfessions, 
		{@value: @Id, @text: @Name, @firstoption: res.Select})			
)
page.Call( @hookSecondariesChangeEvent );&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;As you can see, I ask the page to replace the element secondaries with the newly rendered select element. I then acll the hookSecondariesChangeEvent function, since I actually replace the entire element, and not just its content. I am doing this because I don't feel like extracting the part that renders just the options from the Form.Select() method, but I will probably will the next time I need it.&lt;/p&gt;
&lt;p&gt;The GetTertiaryProfressionsBySecondary.brailjs is actually simpler:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;page.Replace( 'tertiaries', 
	Form.Select('tertiaries',TertiaryProfessions, 
		{@value: @Id, @text: @Name, @firstoption: res.Select})			
)&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Again, there are probably betters way, but this is the one I just came up with.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/9752.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2007/10/08/Cascading-Drop-Downs-in-MonoRail.aspx</guid>
            <pubDate>Mon, 08 Oct 2007 11:29:35 GMT</pubDate>
            <comments>http://ayende.com/Blog/archive/2007/10/08/Cascading-Drop-Downs-in-MonoRail.aspx#feedback</comments>
            <slash:comments>15</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/9752.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Handling javascript localization in Mono Rail</title>
            <link>http://ayende.com/Blog/archive/2007/10/07/Handling-javascript-localization-in-Mono-Rail.aspx</link>
            <description>&lt;p&gt;I run into the issue of having to alert the user of some error, and it brought home the fact that English &amp;amp; Hebrew are not easy to mix. In fact, code such as this is consider a very bad sign, usually code that you don't really want to touch, see or believe in:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/HandlingjavascriptlocalizationinMonoRail_F0EF/image.png" atomicselection="true"&gt;&lt;img height="35" alt="image" src="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/HandlingjavascriptlocalizationinMonoRail_F0EF/image_thumb.png" width="286" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;So, we need some sort of a way to externalize those strings, even if the only language that this application is going to use is Hebrew, simply because of the pain of mixing the two together.&lt;/p&gt; &lt;p&gt;After thinking about it for a while, I decided to create this view (JavascriptResources/index.brail):&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&amp;lt;%
&lt;span style="color: #0000ff"&gt;for&lt;/span&gt; de &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; controller.Resources:
	resourceName = de.Key
%&amp;gt;
	&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; ${resourceName} = {
	&amp;lt;% &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; item &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; GetParameter(resourceName): %&amp;gt;
		${item.Key}: '${item.Value.Replace("&lt;span style="color: #8b0000"&gt;'&lt;/span&gt;","&lt;span style="color: #8b0000"&gt;\\'&lt;/span&gt;") }',
	&amp;lt;% &lt;span style="color: #0000ff"&gt;end&lt;/span&gt; %&amp;gt;
		Empty: ''
	};
&amp;lt;%
&lt;span style="color: #0000ff"&gt;end&lt;/span&gt;
%&amp;gt;&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;And here is the definition of the controller:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;[Resource("&lt;span style="color: #8b0000"&gt;Processes&lt;/span&gt;", "&lt;span style="color: #8b0000"&gt;MyApp.Resources.Javascript.Processes&lt;/span&gt;")]
[Resource("&lt;span style="color: #8b0000"&gt;Errors&lt;/span&gt;", "&lt;span style="color: #8b0000"&gt;MyApp.Resources.Javascript.Errors&lt;/span&gt;")]
[Resource("&lt;span style="color: #8b0000"&gt;Messages&lt;/span&gt;", "&lt;span style="color: #8b0000"&gt;MyApp.Resources.Javascript.Messages&lt;/span&gt;")]
&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; JavascriptResourcesController : Controller
{
	&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Index()
	{
		
	}
}
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;But what the hell does this &lt;em&gt;do, &lt;/em&gt;anyway? Not much, actually, but it will iterate over all the registered resources for the controller, and output something that looks like this for each of those resources:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; Processes = {
 	EmploymentType: 'Employment Type',
	Details: 'Details',
	Dates: 'The dates',
	Empty: ''
};&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;The nice thing is that I can now write: alert(Errors.RecursiveError);*. As a side affect (as I said, the application is just in Hebrew so I don't care about that much), I also get the usual benefits of localization.&lt;/p&gt;
&lt;p&gt;* You have to read Hebrew to get the joke, I am afraid.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/9748.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2007/10/07/Handling-javascript-localization-in-Mono-Rail.aspx</guid>
            <pubDate>Sun, 07 Oct 2007 16:10:39 GMT</pubDate>
            <comments>http://ayende.com/Blog/archive/2007/10/07/Handling-javascript-localization-in-Mono-Rail.aspx#feedback</comments>
            <slash:comments>5</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/9748.aspx</wfw:commentRss>
        </item>
    </channel>
</rss>