Title: Developing AJAX Web applications with Castle Monorail
1Developing AJAX Web applications with Castle
Monorail
- David De Florinier
- Gojko Adzic (gojko_at_gojko.com)?
- Skills Matter
- 12/06/08
2Why Monorail for Ajax Apps?
- Plumbing handled by the framework
- Lots of helpers
- Integrated with Prototype and Scriptaculous
- Benefits from Castle Project integrations
3- Write AJAX apps without much more code than if
you were writing a - non-ajax one!
4- Options for AJAX with Monorail
- Preparing the application
- Proxying calls
- Monorail helpers and effects
- How it all comes together
- Some best practices and pitfalls
5Option 1 Rails-style JS Generator
- Ajax actions send commands to the page
- Use NJS views instead of VM for Ajax Actions
- Mix and match Ajax and Non-Ajax calls
- Reuse partial templates
6Option 2 Use Prototype and build parts of the
page with actions
- Ajax actions build only parts of the page
- Use AjaxHelper to coordinate calls
- Coordinate page updates from the browser side
- Cleaner code on the server, more focused
- Option to use JSONHelper to render results
- Option to use controller proxies
7Option 3 Transparent JSON controller binding
- Actions exported to the web page
- Coordinate rendering on the client
- Clean code, all plumbing done by MR
- Use JSonReturnBinder and JSonBinder
- ... but not yet complete
8Preparing the application for AJAX
- Add prototype.js library
- AjaxHelper.GetJavascriptFunctions()?
- ... will render ...
- src"/MonoRail/Files/AjaxScripts.rails"
-
- Use Ajax.Request and Ajax.Updater
9Use AjaxHelper to create elements
- AjaxHelper.ButtonToRemote("Delete",
"DeleteHero.rails", " Complete'heroActionCallba
ck(request)' , with'\'iditem.Id\'' ")? - ... will render ...
- Ajax.Request('DeleteHero.rails',
onCompletefunction(request)
heroActionCallback(request) ,
asynchronoustrue, evalScriptstrue,
parameters'id3') return false"/ - Methods provided for links, buttons, observers,
autocompletion, forms
10Use AjaxHelper to Build Forms
- AjaxHelper.BuildFormRemoteTag("/Heroes/CreateHero
.rails", "update'heroList',formid'heroForm',
Complete'document.pageHelper.heroes.listRefreshed
()'")? - ... will render ...
- CreateHero.rails" enctype"multipart/form-data" on
submit"new Ajax.Updater('heroList',
'/Heroes/CreateHero.rails', onCompletefunction(r
equest) document.pageHelper.heroes.listRefreshed
() , asynchronoustrue, evalScriptstrue,
parametersForm.serialize(this)) return
false"
11AjaxHelper parameters
- with
- form
- update
- success/failure
- evalScripts
- complete
- onSuccess/onFailure
- before/after/condition
12Preparing controllers for AJAX
- Implemented as a method on the controller
- Tightly focused
- Promotes reusability
- Reduces risk due to change
- Simplifies unit tests
13Generating controller proxies
- Decorate methods with AjaxAction attribute
- AjaxAction
- public void DeleteHero(int id)
- Use AjaxHelper.GenerateJSProxy
- AjaxHelper.GenerateJSProxy("controllerProxy")?
- .. then the following is rendered
- var controllerProxy
-
- deleteHero function(id, callback)
- var rnew Ajax.Request('/Heroes/De
leteHero.rails', method 'get', asynchronous
!!callback, onComplete callback, parameters
'_\x26id'id'') - if(!callback) return
r.transport.responseText -
14Synchronous / asynchronous calls
- Proxies allow both synchronous and asynchronous
calls to be made - Supply a callback function to make asynchronous
call - function heroActionCallback(result)
- var response result.responseText.evalJSON()
- alert(response.message)
-
- function deleteHero(id)
- controllerProxy.deleteHero( id,
heroActionCallback) -
15Synchronous / asynchronous calls
- Use synchronous calls ONLY if you don't want
anything else to happen - Prefer async calls for better performance
- Async replies can come in different order
- Number of simultaneous calls to the same domain
is very limited
16Monorail layout strategies
- Monorail has a concept of layouts
- AJAX actions would not have a layout
- ... but index method would
- There is more than one way to achieve this
- Two methods illustrated
- NJS templates don't use layouts (JS Generation)?
17AJAX layout strategy 1
- No layout on the class
- Index method has a layout
- Layout("default")
- public void Index()?
- Simple, quick, no additional code
- ... but ties the action to blank layout for all
calls
18AJAX layout strategy 2
- Use filter to kill layout on AJAX calls
- public class AjaxLayoutFilter IFilter
- public bool Perform(ExecuteEnum exec,
IRailsEngineContext context, Controller
controller) - if(IsAjaxRequest(context))
controller.CancelLayout() - return true
- //from http//blechie.com/
- public static bool IsAjaxRequest(IRailsEng
ineContext context) - string requestedWith
context.Request.Headers"X-Requested-With" - if (string.IsNullOrEmpty(requestedWith
)) return false - return requestedWith.Equals("XMLHttpRe
quest",StringComparison.InvariantCultureIgnoreCase
) -
19Script.aculo.us integration
- A JavaScript framework which is for UI sugar.
- Install scripts using ScriptaculousHelper.Instal
lScripts()? - Add effects using the ScriptaculousHelper
VisualEffect method -
- ScriptaculousHelper.VisualEffect('ToggleBlind',
'colOne')? - ScriptaculousHelper.VisualEffect('ToggleAppear',
'colThree')? - ScriptaculousHelper.VisualEffect('ToggleBlind',
'colTwo')? -
20Script.aculo.us Drag Drop
- Make elements draggable
- new Draggable(element, reverttrue)
- Make elements Drop zones
- Droppables.add( element, hoverclass
'dropHover', accept 'dropelementclassname',
onDrop dropPower ) - Drop delegate accepts both elements as parameters
- function dropPower(draggable,droparea)
21Stuff to remember
- JSON binding will probably be complete soon
- Use context for generic shared templates
- Use AjaxHelper for Prototype integration
- Use ScriptaculousHelper for effects
- You can use Prototype and Scriptaculous in JS
code directly - Use async calls for better performance
22... a few links
- http//www.castleproject.org/MonoRail
- http//hammett.castleproject.org
- http//www.ayende.com/blog
- http//www.prototypejs.org
- http//script.aculo.us
23What next?
- Beers straight away
- ALT.NET meeting next week
- TDD with Databases in two weeks
- ALT.NET talk at Skills Matter on July 31st