Ajax and MonoRail

This is a repost of an example I created for using.castleproject.orgI just used some Ajax functionality on another project and I figured I would post some code of what I found out after struggling with a couple of pieces for awhile.MonoRail utilizes the Prototype Javascript Framework to perform Ajax calls, so worst case scenario, you can write javascript code directly against the prototype library. All you need to do on your MonoRail view is include the javascript declaration by placing the following at the top of your view:

$AjaxHelper.GetJavascriptFunctions()

First, You’ll need to look at the Castle Project AjaxHelper documentation. You don’t need to memorize the whole thing, but pay close attention to LinkToRemote and ButtonToRemote. There is ALOT of stuff in there, so try not to feel overwhelmed. I know I did at first =)For my project, I had to input some price information, add the price to a collection on the controller, and then display it on the view before continuing. The easiest way to do this is to serialize the form and pass it when performing the Ajax call, Ajax then invokes an Action on your controller, and you respond by either rendering some text, or rendering another view into the “update” div. Here is my code for my ButtonToRemote: 

$AjaxHelper.ButtonToRemote("Add Price", "addprice.rails", $DictHelper.CreateDict("update=prices","with=Form.serialize($('itemform'))"))


 Let’s step through the parameters one by one.

  • “Add Price”
    • This is the text that will be shown on the button. pretty basic
  • “addprice.rails”
    • This is the action to call on the controller
  • $DictHelper.CreateDict(“update=prices”,“with=Form.serialize($(‘itemform’))”))
    • The dictionary values to pass is where it is a little tricky. “update=prices” is the id of the div that Ajax will update upon sending a response. So if you render text, or another view it will appear within this div id. The second dictionary parameter is for values that you want to pass to your action, hence the with= parameter. You can pass the entire form as I have, or single values such as an id

Note, that I am using $(‘itemform’) instead of ‘this’ when telling the AjaxHelper to serialize the form. This refers to the id value of the form tag. I tried it both ways and it didn’t seem to want to work the other way. Perhaps someone else has a different experience with this. Next, setup your action to do whatever processing you need and then Render a view like so:

public void AddPrice([DataBind("price")] Price price)
{
// Do some work with price object
RenderView("priceList");
CancelLayout();
}

The RenderView call will render the view called priceList.vm that is located in the same directory as the Controllers view. Then you have to call CancelLayout to cancel the layout processing which occurs last, otherwise the layout will also be rendered within the div. If you call RenderText it will simply output that text into the div.The reason I am rendering a view into the div is because it is displaying a collection of prices along with edit/delete links for each. In its basic form, the functionality here is the same as an Ajax DataGrid/GridView if we were in the WebForms world, except without the burden of Page lifecycle.On a project I was working on at my workplace, I needed to expand/collapse divs and upon expanding I make an Ajax call to the database to grab the detail view of the expanded div. When I created that, I found it was easier to create a custom javascript function in which I made a call via the prototype library using an Ajax.Request. There are many things you can leverage with using the Prototype framework through MonoRail and the sky is the limit. Check the Castle Project Forum for helpful information, or you can search through the Castle Project Users Newsgroup.Another good place to start is to read the PrototypeJS documentation. This is recommended because all MonoRail is doing is just wrapping the calls to ProtoType. Hopefully in the near future we might see a more rich ajax framework arise from MonoRail, but at the moment I think there is alot more areas that can be focused on within Castle rather than dump time into a custom built Ajax Framework. As they say, If it ain’t broken, then don’t fix it! Not at least until there is a large enough following.