Devlico.Us
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @devlicious

Mike Nichols - Son Of Nun Technology

  • Ordering Form Collection Parameters For MonoRail using jQuery

    On my current app we are using ajax heavily for updating forms, often with the response getting injected into an table or unordered list. The entire form is then posted for the action which will actually change state in the domain.

    For example, say we have a 'NewItem' form (and have several properties):

    <form action="myaction.castle">
        
       
    <label for="newItem_Name">Name</label>
       
    <input type="text" name="newItem.Name" id="newItem_Name"/>
        <
    label for="newItem_Phone">Name</label>
       
    <input type="text" name="newItem.Phone" id="newItem_Phone"/>
       
    <!--10 other properties-->
       
    <input type="submit">Save</input>
    </form>
     
    With the action on the controller:
    public void myaction([DataBind("newItem")] ItemDTO item) 
    {
      
    PropertyBag["item"] = item;
      
    RenderView("ViewWithSophisticatedFormattingForItems");
    }
     
    This simply pushes back an item using the data provided and jquery appends the table with:
    <tr><td><% output item.Name %></td></tr>
    <tr style='display:none;'><td><% output Form.TextField("item.Name") %></td></tr>
     
    The client will toggle between 'readonly' and 'edit' modes to change data inline.
     
    So this would result in multiple rows of 'item.Name' and 'item.Phone', etc. and the DataBinder will choke if you try this:
    public void UpdateToDomain([DataBind("item")] List<ItemDTO> items) 
    {
      
    //do stuff in domain
    }

    As magical as MonoRail and her SmartDispatcherController is, she has to know which value belongs to which item in a collection. The lack of indices in the params will therefore cause arrays of 'Value's for a single ItemDTO instance.

    My first thought was to do a custom implementation of IParameterBinder + DataBinder combo that parses out the params and tries to split them into multiple instances. This is too difficult though since not all fields may be present for an instance.

    So to keep the items in a collection (like table rows or unordered lists) nicely indexed, I created a plugin that handles all the form elements for me. After ajax calls that load data into a table or ul, I can just call the plugin on the rows and all forms elements remain in their appropriate order. Similarly I can unindex forms for posting in the format the action expects. I can similarly just reorder indexes. 

    This just preserves the id and name convention used throughout monorail (with "_" and "[index]"  delimiters respectively). It also changes the 'for' attribute on the label elements for fun.

    This is chainable.

    To use:

    $("table.specimens > tbody tr.edit").indices("on"); //index all rows with class 'edit' 
    $("table.specimens > tbody tr.edit").indices("off"); //remove index on all rows with class '.edit'
    $("table.specimens > tbody tr.edit").indices("ordered"); //ordered existing indices
    $("table.specimens > tbody tr.edit").indices();//toggle indexed/nonindexed mode
    //specify the parameterName prefix if you are indexing on a nested collection
    $("table.specimens > tbody tr.edit").indices("on",{parameterName:'mainclass.nestedObjects'});
    //customize whether a new row should increment the index (default is to skip increments on items with class 'repeat-index')
    $("table.specimens > tbody tr.edit").indices("on",{isRepeatedIndex:function(){...});

     

    And the plugin:

    /***indices plugin for ordering form elements in a group
        @mode (String) : 
            "on" (index elements if not already indexed), 
            "off" (unindex elements if already indexed), 
            "toggle" (toggle between "on" and "off" modes),
            "ordered" (reorder indices of indexed items, or )
        @options (hash) :
            @parameterName (String) : the parameter name to index; if empty, uses the 'name' attribute up to the first '.'
            @isRepeatedIndex (predicate[current item]) : return 'true' to repeat the index (for things like hidden rows, etc); default is a class name 'repeat-index'
        
    ***/

            
    (function($) {
       
    $.fn.indices = function(mode, options) {
           
    mode = mode || "toggle";
           
    var defaults = {
               
    parameterName: "[a-zA-Z0-9]+",
               
    isRepeatedIndex: function(item) { return $(item).is(".repeat-index"); }
           
    };
           
    var opt = $.extend(defaults, options);

           
    var reIndexedName = new RegExp("^(" + opt.parameterName + ")\\[(\\d+)\\]\\.", "gi");
           
    var reIndexedId = new RegExp("^(" + opt.parameterName.replace(".", "_") + ")_\\d+\\_", "gi");
           
    var reNonIndexedName = new RegExp("^(" + opt.parameterName + ")\\.", "gi");
           
    var reNonIndexedId = new RegExp("^(" + opt.parameterName.replace(".", "_") + ")_", "gi");
           
    var changeStrategy = null;
           
    var ndx = -1;

           
    var unindexElement = function(el, ndx) {
               
    if (el.name) {
                   
    $(el).attr("name", el.name.replace(reIndexedName, "$1."));
               
    }
               
    if (el.id) {
                   
    $(el).attr("id", el.id.replace(reIndexedId, "$1_"));
               
    }
               
    if ($(el).attr("for")) {
                   
    $(el).attr("for", $(el).attr("for").replace(reIndexedId, "$1_"));
               
    }
           
    };

           
    var indexElement = function(el, ndx) {
               
    if (el.name) {
                   
    $(el).attr("name", el.name.replace(reNonIndexedName, "$1[" + ndx + "]."));
               
    }
               
    if (el.id) {
                   
    $(el).attr("id", el.id.replace(reNonIndexedId, "$1_" + ndx + "_"));
               
    }
               
    if ($(el).attr("for")) {
                   
    $(el).attr("for", $(el).attr("for").replace(reNonIndexedId, "$1_" + ndx + "_"));
               
    }
           
    };

           
    var reindexElement = function(el, ndx) {
               
    if (el.name) {
                   
    $(el).attr("name", el.name.replace(reIndexedName, "$1[" + ndx + "]."));
               
    }
               
    if (el.id) {
                   
    $(el).attr("id", el.id.replace(reIndexedId, "$1_" + ndx + "_"));
               
    }
               
    if ($(el).attr("for")) {
                   
    $(el).attr("for", $(el).attr("for").replace(reIndexedId, "$1_" + ndx + "_"));
               
    }
           
    };
           
    return this.each(function(idx, item) {
               
    if (!opt.isRepeatedIndex(item)) {
                   
    ndx++;
               
    }

               
    $(this).find(":input,label").each(function() {

                   
    if (!changeStrategy) {
                       
    //evaluate only once per collection
                        if (!this.name && !this.id) {
                           
    //nothing to do here
                            return;
                       
    }
                       
    changeStrategy = function() { }; //default empty function
                        var isIndexed = this.name ? reIndexedName.test(this.name) : this.id ? reIndexedId.test(this.id) : false;
                       
    if (mode == "ordered" && !isIndexed) {
                           
    mode = "on"; //we already do ordered indexing so just use the 'on' mode
                        }

                       
    if (isIndexed) {
                           
    if (mode == "off" || mode == "toggle") {
                               
    changeStrategy = unindexElement;
                           
    } else if (mode == "ordered") {
                               
    changeStrategy = reindexElement
                           
    }
                       
    } else {
                           
    if (mode == "on" || mode == "toggle") {
                               
    changeStrategy = indexElement;
                           
    }
                       
    }
                   
    }
                   
    changeStrategy(this, ndx); //fire

               
    });
           
    });

       
    };

     

    I don't like having to scrub the data like this on the client side, but I really can't think of a way to keep parameters being sent valid while still updating data in small chunks without passing indexes back and forth. Any other approaches would be great to hear!

  • Considerations For Using PostSharp

    I recently started using PostSharp for implementing AOP into my current project. It's a great project and really simplifies some specifications we have that could have been cumbersome. Introducing this into an environment that is using NAnt and development using TDD took some exploration for me so I thought I'd log some things I had to overcome.

    Building from NAnt

    I saw that there was an NAnt task created for PostSharp but I either couldn't get it going, or I couldn't find it ( I can't remember). I ended up just using the command line app included with PostSharp, so I have an NAnt target that invokes the utility from within my project default.build file:

        <target name="postsharp">        
           
    <copy file="${build.dir}/${project::get-name()}.dll" tofile="${build.dir}/Pre.${project::get-name()}.dll" overwrite="true"/>        
             <
    exec program="${build.dir}/PostSharp.exe">
               
    <arg value="${build.dir}/Default.psproj" />
                <
    arg value="${build.dir}/Pre.${project::get-name()}.dll" />
                <
    arg value="/P:Output=${build.dir}/Post.${project::get-name()}.dll" />
                <
    arg value="/P:ReferenceDirectory=${build.dir}" />
                <
    arg value="/P:SearchPath=${build.dir}" />
                <
    arg value="/P:IntermediateDirectory=${build.dir}" />
                <
    arg value="/P:CleanIntermediate=False" />
                <
    arg value="/P:MSBuildProjectFullPath=D:\path\to\src\app\Cei.MaterialsTesting\${project::get-name()}.csproj" />
                <
    arg value="/P:SignAssembly=True" />            
                <
    arg value="/P:PrivateKeyLocation=${root.dir}/my.snk" />            
            </
    exec>

     

    A few things to note here. I had to first make a copy of the assembly I am manipulating and rename it with an 'Pre.assemblyname' prefix (or whatever). The dll was getting locked during the build so PostSharp would complain.  The output of PostSharp is 'Post.<assemblyname>' and then I copy that after the utility runs. I think I had the same locking issue that forced me to do this.

    Notice I am doing everything in my build directory so I had previously copied over all required PostSharp files to do that when I copy all other dependencies:

    <copy todir="${build.dir}" >
         
    <fileset basedir="${tools.dir}/PostSharp">
           
    <include name="*.dll" />
            <
    include name="*.exe" />
            <
    include name="*.targets" />
            <
    include name="*.psproj" />
            <
    include name="*.config" />
            <
    include name="*.psplugin" />        
            <
    include name="*.version" />        
          </
    fileset>
       
    </copy>
     

    TDD Becomes Heavy

    The compilation times are considerably larger due to the post-compilation magic. When you are used to almost instant feedback in the IDE this starts out as being an irritation then begins to affect how I write my tests - not good. I will probably pull my aspect related tests into their own test assembly and then target assemblies that are actually used in the app will require some kind of environment condition on the PostSharp targets setup in the .csproj files. I haven't resolved the better approach to take to get around this.  I know my own tendency toward impatience will cause me to write bad tests, or not at all, if I have to wait for each rebuild to take so long so I need to keep it quick.

  • Sorry I am so immature

    From NH user group:

    Image and video hosting by TinyPic"I have a "pepe" and I know it is not a proxy"

    If this doesn't belong in a software developer's adaptation of  Napoleon Dynamite, I don't know what would.

  • Enabling auto-detection of response type in jQuery

    Sometimes you don't know what type of document the server is going to return, so it would be nice to have the ajax handler deal with the response as the server is directing it to.

    JQuery doesn't have this baked in (I have had a ticket for ages there to implement it), but a workaround is to roll your own handler. The data filter that was introduced in the latest round of jquery is useless since you don't have access to the response object (and thus the header) and doing hacky string parsing was brittle. To replace the current handler, just roll your own httpData function that replaces the native function in jquery.

    Using jquery 1.2.6 +  here is a patch you can add after the jquery reference on your page:

    * patch for dynamic evaluation of xhr responseType to set the dataType on jQuery */
    jQuery.extend({
     
    httpData: function( xhr, type, s ) {        
           
    var ct = xhr.getResponseHeader("content-type"),
                   
    xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
                   
    script = type == "script" || !type && ct && ct.indexOf("script") >= 0,
                   
    json = type == "json" || !type && ct && ct.indexOf("json") >= 0,
                   
    data = xml ? xhr.responseXML : xhr.responseText;
                    
                   
    if ( xml && data.documentElement.tagName == "parsererror" )
                       
    throw "parsererror";
                    
                   
    // Allow a pre-filtering function to sanitize the response
                    // s != null is checked to keep backwards compatibility
                    if( s && s.dataFilter )
                       
    data = s.dataFilter( data, type );
                    
                   
    // If the type is "script", eval it in global context
                    if ( script ) 
                       
    jQuery.globalEval( data );

                   
    // Get the JavaScript object, if JSON is used.
                    if ( json )
                       
    data = eval("(" + data + ")");

                   
    return data;
       
    }
    });

     

    All this is doing is what it already does with xml response types...it sniffs the response header and handles appropriately. Now I can let my server determine whether I am generating just some javascript snippet that should get evaluated or some markup that should be pushed into the page without requiring my client ajax method to state it explicitly.

  • SVN revision number discrepancy

    I use VisualSVN for IDE integration of VS.NET and TortoiseSVN. While working on my build script I noticed that while fetching my svn revision number it was different than what was getting reported after a commit within the ide.

    I am hardly source control guru so I wasn't sure what to do to track this down.

    Turns out I needed to do an svn up at the root directory to bring the revision numbers back in alignment as I found in this (PDF) doc.

  • When Flushing Goes Bad: Assigned IDs in NHibernate

    I have an aggregate root that creates another persistent entity and places it in a collection.

    Typically, I try to avoid letting the internal id used within an aggregate boundary seep outside, but for the purpose of mapping the relevant instance to the ui data being sent, I needed to get the id and pass it back to the ui.

    Using this mapping on the newly created entity:

    <class name="AggregateRoot" table="RootsButNotTheBook">
        <!--snip-->
        <set name="ChildEntities" class="ChildEntity" cascade="all"> <!--more-->
    </class>
    <class name="ChildEntity" table="ChildEntities">
            <id name="Id" type="Guid" >
                <generator class="assigned"/>
            </id>
            
        <!--more mapping-->

     

    and trying this code:

    aggregateRoot.CreateChildEntityAndAddToCollection();
    session.Update(aggregateRoot);
    session.Flush();

    Will get me this NHibernate exception:

    NHibernate.StaleStateException: Unexpected row count: 0; expected: 1

    Why? Well, inside my ChildEntity creation logic, I am generating an id for the entity so NHibernate thinks that it is a previously persisted entity ... but of course it isn't.

    To make this work I change my child entity mapping to :

    <class name="ChildEntity" table="ChildEntities">
            <id name="Id" type="Guid" >
                <generator class="assigned"/>
            </id>
            <version name="LastModifiedOn" 
                    type="timestamp" 
                    column="LastModifiedOn" 
                    access="nosetter.camelcase" />
        <!--more mapping-->

    Adding the Versioning element to my entity now lets NHibernate know how to deal with the entity as it should and the code now works swimmingly.

    The Hibernate documentation states:

    A version or timestamp property should never be null for a detached instance, so Hibernate will detact any instance with a null version or timestamp as transient, no matter what other unsaved-value strategies are specified. Declaring a nullable version or timestamp property is an easy way to avoid any problems with transitive reattachment in Hibernate, especially useful for people using assigned identifiers or composite keys!

    Therefore I actually used a nullable DateTime on my ChildEntity class, but things seemed to work even when I used a non-nullable DateTime, so I am not sure what I am missing there. Let me know if there are any errors in anything I present here...

  • jQuery.cascade : Cascading values from forms

     

    First, get it here ...

    Please leave commments/questions on jquery google group at : http://groups.google.com/group/jquery-en.

     

    UPDATE: Fixed bug in ajax extension whereby it was holding a reference to previous data params. Also updated to work with jquery 1.2.6 in demo pack.

    UPDATE 06-09-2008 : Breaking change: I inverted dependency from child==>parent to allow unique data sources for each target of a cascade. See distribution for details.

    A common task is quickly fetching data to respond to changes on web forms. The canonical example is cascading select forms that provide options based on previous selections. However, there are numerous variants of this simple scenario that could be simplified using jquery's plugin pattern. Really, the goal is simple...when something happens on my page, get some data from somewhere and put in something else, with each item looking like I specify.

    Being inspired by the awesome autocomplete plugin here, I adapted their compact code and event delegation pattern to create a simple but powerful plugin for cascading form results into their targets.

    While the initial goal was simply cascading select lists and being able to chain them together, the event delegation made so simple in jquery quickly expanded the potential.

    You can cascade from any kind of element into any other kind of element (for the most part). You can also provide extensions to the plugin easily enough to handle just about anything and it just weighs in at around 100 lines of code. Packed, it's 1.3 kB.

    Events

    There are only two events, loading.cascade and loaded.cascade triggered. You may specify what event will fire the cascade on the parent element. To bind to the cascade events, use the chained binding syntax common in jquery...this lets the control scale without munging up the options. For a great discussion of this technique see here and here .

     

    Usage

    Here are some examples on how to use it:

    With all data being json, using the following structure:

    {'when':'selectedValue','value':'itemValue','text':'itemText'}


       with static list on page:

    $('#myChildSelect').cascade('#myParentSelect', {
    list: [{'when':'A','value':'A1','text':'A1'},{'when':'B','value':'B1','text':'B1'}],
    template: function(item) { return "<option value='" + item.value + "'>" + item.text + "</option>"; },
    match: function(selectedValue) { return this.when == selectedValue; }
    });

    with ajax call (using .ext ):

    $('#myChildSelect').cascade('#myParentSelect', {
    ajax: '/my/url/action',
    template: function(item) { return "<option value='" + item.value + "'>" + item.text + "</option>"; },
    match: function(selectedValue) { return this.when == selectedValue; }
    });

      

    with chained cascading:

    $('#myFirstChildSelect').cascade('#myParentSelect', {
    ajax: {url: '/my/url/action' },
    template: function(item) { return "<option value='" + item.value + "'>" + item.text + "</option>"; },
    match: function(selectedValue) { return this.when == selectedValue; }
    });

    $('#mySecondChildSelect').cascade('#myFirstChildSelect', {
    ajax: {url: '/my/url/action' },
    template: function(item) { return "<option value='" + item.value + "'>" + item.text + "</option>"; },
    match: function(selectedValue) { return this.when == selectedValue; }
    });

     

    add a firstOption for optional lists using the loaded.cascade event:  

    jQuery("#myChildSelect").cascade("#myParentSelect",{    
    timeout: 100,
    list: myDataSource,
    template: function(item) { return "<option value='" + item.Value + "'>" + item.Text + "</option>"; },
    match: function(selectedValue) { return this.When == selectedValue; }
    })
    .bind("loaded.cascade",function(e,parent) { jQuery(this).prepend("<option value='empty' selected='true'>--Select--</option>");});

     

     

     

    The download has a sample page with lots of different setups and usages. Please let me know if you find any bugs or questions. This is my first plugin for jquery so I may be missing some hidden jquery goodness to make the code more elegant.

     

    I will try to get a working demo up soon.

  • Third Party Libraries Organization

    I finally have my CI environment and am wondering what the heck took me so long to take time to get it set up. This has had me looking again at how I set my project folders up. Typically I am using the libraries from Castle/Nhib/Rhino stack and build them all at the same time quite frequently since the Rhino build process simply ROCKS. However I notice everyone putting all their dependencies in separate folders like this:

    • /lib/Castle
    • /lib/NHibernate
    • /lib/Rhino
    • /lib/...

    Personally, I have just thrown all my dependencies in a single /lib folder and haven't come across issues with this. I still keep tools like mbunit or nant in a separate /tools directory.

    My /lib directory isn't as pretty organized looking but like I said most of my dependencies are getting rebuilt at the same time anyways. So what advantage am I missing out on by just throwing everything into a single folder? It has made it much simpler for copying assemblies from other builds (I know I could automate that too).  Am I being overly simplistic?

  • Configuring IIS 6.0 to send mail via SMTP for asp.net applications

    Enabling smtp services for IIS is well documented, but configuring in my environment was more difficult than I would have thought it would be... So this post is partly a note for me as we will be changing out gear soon.

    Our environment is not very exotic...a box acting as an web server, and another box acting as an exchange server. Both are running Win2003.

    First, smtp services must obviously be enabled/running. Here is how.

    Next, in IIS, select the new SMTP Virtual server node and right-click/Properties/Access/Relay. Be sure 'Only the list below' is selected and add '127.0.0.1' (localhost) to your Computers Access list . Finally, deselect 'Allow all computers which successfully authenticate...'. Be very careful not to turn your server into a relay server unless you like being blacklisted .

    Now, at this point I was able to get my mail sent to domains outside my own. So if my webserver was webbox.mydomain.com and it sent mail to mygmail@gmail.com then all worked just fine. But I was unable to send mail internally to other mail accounts (mydomain.com).

    What I failed to do was set up a SMART HOST to route mail to my exchange box.

    To do that, right-click the smtp node in iis/Properties/Delivery/Advanced. Enter the name of the server hosting exchange and deselect 'attempt direct delivery before sending to smart host'.

  • Unobtrusive Growl Messaging Using Monorail Filter

    A clever plugin for jquery recently was released which is an impression of Mac's Growl. It simply displays messages for a period of time or makes them 'sticky'. It also manages multiple messages at a time very nicely and all the styling is external so a real snap to customize. The best part is how simply it is implemented. You simply call

    jQuery.jGrowl(\"My Message Should Appear\", options );

    and you get a popup that gradually fades. Fire off two in quick succession and jgrowl is smart enough to fade them appropriately and provide a global 'close' bar to clear all messages.

    On all projects it seems like the most messages I need to communicate to my users lump into similar categories; 'errors','warnings','messages','success','failure', and so on. Typically these are thrown in either a Flash or PropertyBag collection for consumption by the view.

    I wanted to simplify how I am passing messages to my users regardless of the request type (Ajax/Non) and regardless of whether I use JS Generation to render some view , so I narrowed down to requiring some filter which would handle all calls and inspect specific collections that I can configure that may or may not be populated with messages during the action. This will either append the messages to our http response directly, or using an TransformFilter implementation (an HttpFilter) - more on that later. Using a filter this way let's me avoid having to drop anything on my layout or require any kind of view code. I simply attach this filter to my controller base and it just works.

    First, let's determine what our notifications are:

    public class GrowlNotification 
        { 
            private readonly string key = string.Empty; 
            private IDictionary options; 
    
            public GrowlNotification(string key) 
                : this(key, new HybridDictionary()) 
            { 
            } 
    
            public GrowlNotification(string key, IDictionary options) 
            { 
                this.key = key; 
                this.options = options; 
            } 
    
            public string Key 
            { 
                get { return key; } 
            } 
    
            public IDictionary Options 
            { 
                get 
                { 
                    options = options ?? new HybridDictionary(); 
                    HybridDictionary defaultOptions = new HybridDictionary(); 
                    defaultOptions.Add("sticky", "false"); 
                    defaultOptions.Add("theme", "\""+GetTheme()+"\""); 
                    defaultOptions.Add("speed", "\"slow\""); 
                    CommonUtils.MergeOptions(options, defaultOptions); 
                    return options; 
    
                } 
            } 
            private string GetTheme() 
            { 
                if(string.IsNullOrEmpty(key)) 
                { 
                    return "default"; 
                } 
                return key; 
            } 
    
        }

    'Key' is simply a corresponding value with the key of the Flash/PropertyBag being inspected by the Filter after the action. jGrowl lets us pass a 'theme' to attach an additional class name to the message container on the client side so it is real easy to modify how each message appears using simple css. This will correspond with the 'Key' name.

    Options are obviously the js options jgrowl supports. Each message type can have its own options. So you can, for example,make 'errors' sticky and all other message types fade out after a bit.

     

    Now, let's encapsulate the configuration and make it accessible on the container but provide an sensible default configuration. This configuration will create the GrowlNotifications for the IGrowlGenerator at runtime:

    public interface IGrowlConfiguration 
    { 
        /// <summary> 
        /// Gets the notifications to inject. 
        /// </summary> 
        /// <returns></returns> 
        IEnumerable<GrowlNotification> GetNotifications(); 
        /// <summary> 
        /// Determines whether this the current request is an xhr. 
        /// </summary> 
        /// <returns> 
        ///     <c>true</c> if this instance is ajax; otherwise, <c>false</c>. 
        /// </returns> 
        bool IsAjax(); 
    } 

    'IsAjax()'  simply informs the filter of the request type so that it can handle the response message(s) appropriately. This can be simply sniffing the headers, or using a more elaborate extension I wrote but is outside the scope here.

    Now it's default implementation:

    /// <summary> 
        /// Default configuration for keys <see cref="GrowlFilter"/> will  sniff to inject. It assumes 'errors' and 'success' 
        /// are intended message keys. 
        /// </summary> 
        public class DefaultGrowlConfiguration : IGrowlConfiguration 
        { 
            public virtual IEnumerable<GrowlNotification> GetNotifications() 
            { 
                HybridDictionary errorOptions = new HybridDictionary(); 
                errorOptions.Add("sticky", "true"); 
    
                return new GrowlNotification[] 
                    { 
                        new GrowlNotification("errors", errorOptions), 
                        new GrowlNotification("success"), 
                        new GrowlNotification("failure",errorOptions), 
                        new GrowlNotification("message"), 
                    }; 
            } 
    
            /// <summary> 
            /// Determines whether this the current request is an xhr.  This assumes the <see cref="AjaxRequestExtension"/> is being 
            /// used for request evaluation at runtime. 
            /// </summary> 
            /// <returns> 
            ///     <c>true</c> if this instance is ajax; otherwise, <c>false</c>. 
            /// </returns> 
            public virtual bool IsAjax() 
            { 
                object isAjax = MonoRailHttpHandlerFactory.CurrentEngineContext.Flash[AjaxRequestExtension.IsAjaxKey]; 
                if (isAjax != null) 
                { 
                    return (bool) isAjax; 
                } 
                return false; 
            } 
        }

    Next, we'll separate out how the jgrowl is generated and provide a default implementation. This will be delegated to within the Filter to write the actual javascript using the configuration:

    public interface IGrowlGenerator 
    { 
        string GenerateFrom(IEngineContext context, IController controller, IControllerContext controllerContext); 
    } 
    public class DefaultGrowlGenerator : IGrowlGenerator 
    { 
        private readonly IGrowlConfiguration growlConfiguration; 
    
        public DefaultGrowlGenerator(IGrowlConfiguration growlConfiguration) 
        { 
            this.growlConfiguration = growlConfiguration; 
        } 
    
        public string GenerateFrom(IEngineContext context, IController controller, IControllerContext controllerContext) 
        { 
            if( growlConfiguration == null ) 
            { 
                throw new ArgumentNullException("growlConfiguration"); 
            } 
            StringBuilder scriptContents = new StringBuilder(); 
            bool hasContent = false; 
            IEnumerable<GrowlNotification> notifications = growlConfiguration.GetNotifications(); 
            foreach (GrowlNotification item in notifications ?? new GrowlNotification[0]) 
            { 
                //look in property bag first for message 
                object propBagMsg = controllerContext.PropertyBag[item.Key]; 
                object flashMsg = context.Flash[item.Key]; 
                string msg = string.Empty; 
                if (propBagMsg != null) 
                { 
                    msg = msg + propBagMsg ?? string.Empty; 
                } 
                if (flashMsg != null) 
                { 
                    msg = msg + flashMsg ?? string.Empty; 
                } 
    
                if (!string.IsNullOrEmpty(msg)) 
                { 
                    hasContent = true; 
                    string options = AbstractHelper.JavascriptOptions(item.Options); 
                    scriptContents.AppendFormat("jQuery.jGrowl(\"{0}\", {1} );", msg, options); 
                } 
            } 
            if (hasContent) 
            { 
                string inner = JSUtils.WrapWithTryCatch(scriptContents.ToString()); 
                return "jQuery(document).ready(function() { " + inner + "});"; 
            } 
            return string.Empty; 
        } 
    
    }

    It's worth noting here that this assumes you are expecting the dataType of 'script' in your jquery ajax calls. I set a global using

    $.ajaxSetup({ dataType:"script" });//all calls are returned as js to evaluate

    We can finally implement an Monorail filter that will consume all these services and write the appropriate javascript to our response for jgrowl to handle. Here's the filter:

    public class GrowlFilter : Filter 
    { 
        private bool prependToBodyCloseTag = false; 
        private string growl = string.Empty; 
        private IGrowlConfiguration growlConfiguration = new DefaultGrowlConfiguration(); 
        private IGrowlGenerator growlGenerator; 
        private ModifyResponse responseModifier; 
    
        /// <summary> 
        /// Gets or sets the growl configuration. 
        /// </summary> 
        /// <value>The growl configuration.</value> 
        public virtual IGrowlConfiguration GrowlConfiguration 
        { 
            get { return growlConfiguration; } 
            set { growlConfiguration = value; } 
        } 
    
    
        /// <summary> 
        /// Gets or sets the response modifier. 
        /// </summary> 
        /// <value>The response modifier.</value> 
        public virtual ModifyResponse ResponseModifier 
        { 
            get 
            { 
                if(responseModifier==null) 
                { 
                    responseModifier = DoPrependBodyCloseTag; 
                } 
                return responseModifier; 
            } 
            set { responseModifier = value; } 
        } 
    
        /// <summary> 
        /// Gets or sets the growl generator. 
        /// </summary> 
        /// <value>The growl generator.</value> 
        public IGrowlGenerator GrowlGenerator 
        { 
            get 
            { 
                if(growlGenerator==null) 
                {