1 / 23

Developing AJAX Web applications with Castle Monorail

David De Florinier Gojko Adzic (gojko@gojko.com) ‏ Skills Matter 12/06/08. Developing AJAX Web applications with Castle Monorail. Plumbing handled by the framework Lots of helpers Integrated with Prototype and Scriptaculous Benefits from Castle Project integrations.

baird
Download Presentation

Developing AJAX Web applications with Castle Monorail

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. David De Florinier Gojko Adzic (gojko@gojko.com)‏ Skills Matter 12/06/08 Developing AJAX Web applications with Castle Monorail

  2. Plumbing handled by the framework Lots of helpers Integrated with Prototype and Scriptaculous Benefits from Castle Project integrations Why Monorail for Ajax Apps?

  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

  5. Option #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

  6. Option #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

  7. Option #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

  8. Preparing the application for AJAX • Add prototype.js library $AjaxHelper.GetJavascriptFunctions()‏ ... will render ... <script type="text/javascript" src="/MonoRail/Files/AjaxScripts.rails"> </script> • Use Ajax.Request and Ajax.Updater

  9. Use AjaxHelper to create elements $AjaxHelper.ButtonToRemote("Delete", "DeleteHero.rails", "%{ Complete='heroActionCallback(request)' , with='\'id=${item.Id}\'' }")‏ ... will render ... <input type="button" value="Delete" onclick="new Ajax.Request('DeleteHero.rails', {onComplete:function(request) { heroActionCallback(request) } , asynchronous:true, evalScripts:true, parameters:'id=3'}); return false;"/> Methods provided for links, buttons, observers, autocompletion, forms

  10. Use AjaxHelper to Build Forms $AjaxHelper.BuildFormRemoteTag("/Heroes/CreateHero.rails", "%{update='heroList',formid='heroForm', Complete='document.pageHelper.heroes.listRefreshed();'}")‏ ... will render ... <form id="heroForm" method="post" action="/Heroes/CreateHero.rails" enctype="multipart/form-data" onsubmit="new Ajax.Updater('heroList', '/Heroes/CreateHero.rails', {onComplete:function(request) { document.pageHelper.heroes.listRefreshed(); } , asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">

  11. AjaxHelper parameters • with • form • update • success/failure • evalScripts • complete • onSuccess/onFailure • before/after/condition

  12. Preparing controllers for AJAX • Implemented as a method on the controller • Tightly focused • Promotes reusability • Reduces risk due to change • Simplifies unit tests

  13. Generating controller proxies • Decorate methods with AjaxAction attribute [AjaxAction] publicvoid DeleteHero(int id) {} • Use AjaxHelper.GenerateJSProxy $AjaxHelper.GenerateJSProxy("controllerProxy")‏ .. then the following is rendered var controllerProxy = { deleteHero: function(id, callback) { var r=new Ajax.Request('/Heroes/DeleteHero.rails', {method: 'get', asynchronous: !!callback, onComplete: callback, parameters: '_=\x26id='+id+''}); if(!callback) return r.transport.responseText; } };

  14. Synchronous / 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); }

  15. Synchronous / 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

  16. Monorail 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)‏

  17. AJAX layout strategy #1 • No layout on the class • Index method has a layout [Layout("default")] publicvoid Index()‏ • Simple, quick, no additional code • ... but ties the action to blank layout for all calls

  18. AJAX layout strategy #2 • Use filter to kill layout on AJAX calls publicclassAjaxLayoutFilter : IFilter { publicbool Perform(ExecuteEnum exec, IRailsEngineContext context, Controller controller) { if(IsAjaxRequest(context)) controller.CancelLayout(); returntrue; } //from http://blechie.com/ publicstaticbool IsAjaxRequest(IRailsEngineContext context) { string requestedWith = context.Request.Headers["X-Requested-With"]; if (string.IsNullOrEmpty(requestedWith)) returnfalse; return requestedWith.Equals("XMLHttpRequest",StringComparison.InvariantCultureIgnoreCase); } }

  19. Script.aculo.us integration • A JavaScript framework which is for UI sugar. • Install scripts using $ScriptaculousHelper.InstallScripts()‏ • Add effects using the ScriptaculousHelper VisualEffect method <scripttype="text/javascript"> $ScriptaculousHelper.VisualEffect('ToggleBlind', 'colOne')‏ $ScriptaculousHelper.VisualEffect('ToggleAppear', 'colThree')‏ $ScriptaculousHelper.VisualEffect('ToggleBlind', 'colTwo')‏ </script>

  20. Script.aculo.us Drag & Drop • Make elements draggable new Draggable(element, {revert:true}); • Make elements Drop zones Droppables.add( element, {hoverclass: 'dropHover', accept: 'dropelementclassname', onDrop: dropPower} ); • Drop delegate accepts both elements as parameters function dropPower(draggable,droparea)

  21. Stuff 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

  23. What next? • Beers – straight away • ALT.NET meeting next week • TDD with Databases in two weeks • ALT.NET talk at Skills Matter on July 31st

More Related