PPT slides
Upcoming SlideShare
Loading in...5

PPT slides






Total Views
Slideshare-icon Views on SlideShare
Embed Views



0 Embeds 0

No embeds



Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
Post Comment
Edit your comment

    PPT slides PPT slides Presentation Transcript

    • Developing AJAX Web applications with Castle Monorail David De Florinier Gojko Adzic (gojko@gojko.com) Skills Matter 12/06/08
    • Why Monorail for Ajax Apps?  Plumbing handled by the framework  Lots of helpers  Integrated with Prototype and Scriptaculous  Benefits from Castle Project integrations
    • Write AJAX apps without much more code than if you were writing a non-ajax one!
    •  Options for AJAX with Monorail  Preparing the application  Proxying calls  Monorail helpers and effects  How it all comes together  Some best practices and pitfalls
    • 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
    • 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
    • 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
    • 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
    • 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
    • Use AjaxHelper to Build Forms $AjaxHelper.BuildFormRemoteTag("/Heroes/CreateHero .rails", "%{update='heroList',formid='heroForm', Complete='document.pageHelper.heroes.listRefreshe d();'}") ... will render ... <form id="heroForm" method="post" action="/Heroes/Cr eateHero.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;">
    • AjaxHelper parameters  with  form  update  success/failure  evalScripts  complete  onSuccess/onFailure  before/after/condition
    • Preparing controllers for AJAX  Implemented as a method on the controller  Tightly focused Promotes reusability Reduces risk due to change Simplifies unit tests
    • Generating 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 r=new Ajax.Request('/Heroes/DeleteHero.rails', {method: 'get', asynchronous: !!callback, onComplete: callback, parameters: '_=x26id='+id+''}); if(!callback) return r.transport.responseText; } };
    • 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); }
    • 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
    • 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)
    • AJAX 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
    • AJAX 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(IRailsEngineContext context) { string requestedWith = context.Request.Headers["X-Requested-With"]; if (string.IsNullOrEmpty(requestedWith)) return false; return requestedWith.Equals("XMLHttpRequest",StringComparison.InvariantCultureIgnoreCase); } }
    • Script.aculo.us integration  A JavaScript framework which is for UI sugar.  Install scripts using $ScriptaculousHelper.InstallScripts()  Add effects using the ScriptaculousHelper VisualEffect method <script type="text/javascript" > $ScriptaculousHelper.VisualEffect('ToggleBlind', 'colOne') $ScriptaculousHelper.VisualEffect('ToggleAppear', 'colThree') $ScriptaculousHelper.VisualEffect('ToggleBlind', 'colTwo') </script>
    • 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)
    • 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
    • ... 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
    • 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