Code Highlighting

Thursday, August 16, 2012

And let me draw your attention to the left ...

I would like to take this opportunity to point everybody to this wonderful article: A truly lazy OrderBy in LINQ.
The default OrderBy's execution in LINQ only being somewhat deferred always irked me. This version is much better.

Menno

Monday, August 13, 2012

Sorting a GridView bound to an ObjectDataSource - Speed

Just a short bit of code that dates back to ancient times. I use a lot of GridViews bound to ObjectDataSources for database back-end updating modules. To enable sorting those, you need to define the SortParameterName attribute on the ObjectDataSource, and create an overload on your SelectMethod to takes a string parameter of the name you set. No problem.
The issue is that you now need to implement the sorting yourself.
To sort these there are lots of solutions around, from going over the various sort options in a switch statement, just shipping the sort to your database, or a generic approach using Reflection.

The generic approach is clearly the most flexible, but there is drawback: the performance of reflection is pretty terrible. As soon as you have longer lists, it matters. Nobody wants to wait 10 seconds just to sort a list.
So I took the reflection approach, and implemented it using a DynamicMethod. I'm not posting the code, because it's about 300 lines (including comments), there's a download link at the end.
Using it is easy. Either import the namespace and use the extension method:


public static List<Ticket> GetAll(){
            SqlConnection cnData = new SqlConnection(Data.ConnectionString);
            List<Ticket> dbItem = new List<Ticket>();
            SqlCommand cmdData = new SqlCommand("GetAllTickets", cnData);
            
            /* Yadda yadda, whatever */
            
            return dbItem;
        }

        public static List<Ticket> GetAll(string sortExpression)
        {
            var entities = GetAll();
            
            //calls the extension method
            entities.Sort(sortExpression);

            return entities;
        }


Or just use the IComparer directly:


        public static List<Ticket> GetAll(string sortExpression){
            var entities = GetAll();
            
            entities.Sort(new Tabeoka.PropertyComparer<Ticket>(sortExpression));
            return entities;
        }


Here are the performance numbers (Core 2 Quad, 8 Gb ram. 100,000 items in list):

Sort by Int property:
  • Native method: 00.0592331 s
  • DynamicMethod: 00.2716980 s
  • Reflection: 03.6649998 s
Sort by String property:
  • Native method:  00.3787244 s
  • DynamicMethod: 00.4680498 s
  • Reflection: 03.8817182 s
It's interesting how much faster the native method is compared to the DynamicMethod for the Int property. Clearly we're paying the overhead of the boxing due to casting to object and IComparable. If you're doing lots of sorting Int, you could conceivably write a separate code path. The speed increase is still dramatic compared to Reflection.
Just two more remarks:
  • You can sort by multiple properties. 
  • I included a extension method: List<T>.Sort(string sortExpression)
Download here. Have fun. Some more MVC next time.

Menno

Thursday, August 9, 2012

Chaining javascript function array with callbacks

I'm still working on the MVC website I mentioned earlier. It's one of those sites that, rather than just opening a new page, swoops in the new content through neat jQuery animation and ajax loading of data. Magic!
One of the challenges was the chaining of the necessary animations to render the loaded content.
If we're simply opening another content page in the same language (EN, FR, NL, DE) there are just the  following three animations:
  1. Slide away the current content pane,
  2. Slide in the new content, and
  3. Set the selected node of the menu to the new page
The menu and the set of backgrounds stay the same. If we're switching to the home page of another language though, we're looking at:
  1. Slide away the current content pane
  2. Slide away the current menu
  3. Slide away the current background
  4. Load the backgrounds for the new language, slide in the first
  5. Slide in the new menu
  6. Slide in the content of the home page
  7. Finally set the selected language and page
So depending on the page we're switching from and switching to, we need to run through from 3 up to 10 animations that need to be chained through jQuery/various other javascript callbacks.
I wrote functions that reduce the two pages to their common root, and return an array of animation functions that all take a callback parameter (CPS style). Then I use the following functions to run through them sequentially:

function startAnimation(animationFunctions, finalFunction) {
    var status = new animationStatus(animationFunctions, finalFunction);
    
    status.Delegates[0](function() {
        continueAnimation(status);
    });
}

function continueAnimation(status) {
    status.CurrentIndex++;
    if (status.CurrentIndex >= status.Delegates.length) {
        if (status.FinalFunction)
            status.FinalFunction();
    } else {
        status.Delegates[status.CurrentIndex](function() {
            continueAnimation(status);
        });
    }
}

function animationStatus(delegates, finalFunction) {
    this.Delegates = delegates;
    this.CurrentIndex = 0;
    this.FinalFunction = finalFunction;
}

I use the 'continueAnimation' function to chain the functions in the array. The callback closes over the 'status' variable. There's an optional 'finalFunction' parameter to be called after the end of the array has been reached. Obviously you need to make sure the callback always gets called in your animation function. Here is, as an example, the function to show the menu:

function(animationDone) {
    if (targetConfig.Menu == 'LanguageRoot') {
        $("#languagemenu").hide();
        $("#menu").append(renderMenu(data.MainMenuItems));
        $("#rootmenu").show();
    } else {
        $("#languagemenu").show();
        $("#rootmenu").hide();
    }
    $("#menu").animate({
        left: '0px'
    }, 400, animationDone);
}

Obviously functions with callbacks are nothing new. Loading them all into an array makes it easier to dynamically compose an animation though. It also eliminates some mental overhead: just set your animations in the right order, and fire away. You can think of your entire array as just one function, with the finalFunction callback as the only callback.

Menno

Monday, August 6, 2012

European cookie law and classic asp

The EU cookie law is being rolled out as we speak. The Netherlands specifically have already passed the necessary national laws, and dutch websites are already being checked for compliance (even though violations will only yield a warning, not a fine yet).
Those of us who have classic asp legacy sites may have noticed something disconcerting in dealing with this: there is no way to disable session cookies in asp on a per-request basis. You can disable asp sessions altogether for your entire application, and there is an option to disable the session for a single page (but session cookies will still be sent ). Your configuration may be different, but for what it's worth, here's what has worked for us:
You'll need:
  • ASP.NET on your server,
  • IIS 7 or higher, and
  • your application pool in integrated mode
The more perceptive of you will have already figured out where this is going. I am simply going to have ASP.NET remove the cookies the asp handler generates. I wrote a class CookieMonsterModule (because it eats cookies, see?) that checks for a custom header, and removes the cookies if it can't find that header:


using System;
using System.Web;

namespace Tabeoka.CookieMonster
{
    public class CookieMonsterModule : IHttpModule
    {
        public void Dispose() { }

        public void Init(HttpApplication context)
        {
            context.PostRequestHandlerExecute += new EventHandler(CheckEnableCookies);
        }

        public static void CheckEnableCookies(object sender, EventArgs e)
        {
            var response = HttpContext.Current.Response;

            if (!"true".Equals(response.Headers["enablecookies"]))
            {
                // Yum Yum
                response.Headers.Remove("SET-COOKIE");
            }
        }
    }
}

As you can see, all you need to have cookies make it through, is set the 'enablecookies' header to true:

<%@Language=Javascript %>

<%
Response.AddHeader("enablecookies", "true");
%>

I have made a neat little package at http://www.tabeoka.be/downloads/ClassicAspCookieMonster.zip . It includes a minimal web.config that loads the httpmodule, and the dll itself. You can just copy it into the root of your classic asp app, and start using it (given your configuration meets the requirements). Feel free to take the idea and run with it.

Menno

Friday, August 3, 2012

Binding a TreeView to a custom data type

I'm currently working on an MVC-based website. For managing the database I've elected to go with a classic GridView/DetailsView WebForms solution though, mostly because I have the webcontrols and the old code to make that the quicker solution.
One of the things that needs editing is the menu: a simple Key | ParentKey | MenuKey | Name | Url table (MenuKey because I have more than one menu). I bound a TreeView control to this menu using a set of classes I wrote a while ago to bind a TreeView to a folder structure. I decided to share my code, because it's considerably easier to use than anything else I've been able to find online.
I've based my code on the following article: http://www.codeproject.com/Articles/19639/Implementing-IHierarchy-Support-Into-Your-Custom-C . I was able to get my menu items bound to my TreeView using this method. It does not seem reasonable to have to write the same type of code every time I want to bind to a custom data type though. What's more; I'm adding a collection class, simply to implement the IHierarchicalEnumerable interface. The methods I'm simply patching through to existing methods and properties. I'm a programmer, not a plumber.
So here is a generic implementation of IHierarchyData and IHierarchicalEnumerable (download link at the end):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;

namespace Tabeoka
{
    /// <summary>
    /// Utility class for creating a hierarchical data source
    /// </summary>
    public static class HierarchyData
    {
        /// <summary>
        /// Returns a hierarchical data list containing only the root item
        /// </summary>
        /// <typeparam name="T">The data type used for building up the hierarchical data source</typeparam>
        /// <param name="root">The root data item</param>
        /// <param name="childSelector">A delegate that returns the child items of the item passed as an argument</param>
        /// <param name="parentSelector">A delegate that returns the parent item of the item passed as an argument, or null if root</param>
        /// <param name="pathSelector">A delegate that is called for the path of the current item as a string</param>
        /// <returns></returns>
        public static HierarchyDataList<T> GetData<T>(T root, Func<T, IEnumerable<T>> childSelector, Func<T, T> parentSelector, Func<T, string> pathSelector) where T : class
        {
            if (root == null)
                throw new ArgumentNullException("root");
            
            if (childSelector == null)
                throw new ArgumentNullException("childSelector");
            
            if (parentSelector == null)
                throw new ArgumentNullException("parentSelector");
            
            if (pathSelector == null)
                throw new ArgumentNullException("pathSelector");

            return new HierarchyDataList<T>(
                new List<T> { root },
                childSelector,
                parentSelector,
                pathSelector
                );
        }

        /// <summary>
        /// Wrapper class for the data type that implements IHierarchyData 
        /// </summary>
        /// <typeparam name="T">The underlying data type</typeparam>
        public class HierarchyDataItem<T> : IHierarchyData where T : class
        {
            internal T DataItem { get; set; }
            internal Func<T, IEnumerable<T>> ChildSelector { get; set; }
            internal Func<T, T> ParentSelector { get; set; }
            internal Func<T, string> PathSelector { get; set; }

            internal HierarchyDataItem(
                T dataItem,
                Func<T, IEnumerable<T>> childSelector,
                Func<T, T> parentSelector,
                Func<T, string> pathSelector
                )
            {
                DataItem = dataItem;

                this.ChildSelector = childSelector;
                this.ParentSelector = parentSelector;
                this.PathSelector = pathSelector;
            }

            #region IHierarchyData Members

            /// <summary>
            /// Gets the child items wrapped in a IHierarchicalEnumerable
            /// </summary>
            /// <returns>A HierarchyDataList&lt;T&gt;</returns>
            public IHierarchicalEnumerable GetChildren()
            {
                return new HierarchyDataList<T>(
                        ChildSelector(DataItem),
                        this.ChildSelector,
                        this.ParentSelector,
                        this.PathSelector
                    );
            }

            /// <summary>
            /// Gets the parent item, and wraps it in a HierarchyDataItem
            /// </summary>
            /// <returns>A HierarchyDataItem&lt;T&gt;, or null if not found</returns>
            public IHierarchyData GetParent()
            {
                var parent = this.ParentSelector(DataItem);
                if (parent != null)
                    return new HierarchyDataItem<T>(
                        parent,
                        this.ChildSelector,
                        this.ParentSelector,
                        this.PathSelector
                        );

                return null;
            }

            /// <summary>
            /// Checks if there are any child nodes, and returns true if there are
            /// </summary>
            public bool HasChildren
            {
                get
                {
                    return this.ChildSelector(DataItem).Count() > 0;
                }
            }

            /// <summary>
            /// The underlying data object
            /// </summary>
            public object Item
            {
                get { return DataItem; }
            }

            /// <summary>
            /// Is supposed to return the logical path according to the underlying data,
            /// just calls the pathSelector.
            /// </summary>
            public string Path
            {
                get { return PathSelector(DataItem); }
            }

            /// <summary>
            /// TypeOf(T)
            /// </summary>
            public string Type
            {
                get { return typeof(T).ToString(); }
            }

            #endregion
        }

        /// <summary>
        /// A list of T that implements IHierarchicalEnumerable
        /// </summary>
        /// <typeparam name="T">The underlying data type</typeparam>
        public class HierarchyDataList<T> : List<T>, IHierarchicalEnumerable where T : class
        {
            internal Func<T, IEnumerable<T>> ChildSelector { get; set; }
            internal Func<T, T> ParentSelector { get; set; }
            internal Func<T, string> PathSelector { get; set; }

            internal HierarchyDataList(
                IEnumerable<T> items,
                Func<T, IEnumerable<T>> childSelector,
                Func<T, T> parentSelector,
                Func<T, string> pathSelector
                )
                : base(items)
            {

                this.ChildSelector = childSelector;
                this.ParentSelector = parentSelector;
                this.PathSelector = pathSelector;
            }

            #region IHierarchicalEnumerable Members

            /// <summary>
            /// Wraps the enumeratedItem object in a HierarchyDataItem
            /// </summary>
            /// <param name="enumeratedItem">The data item</param>
            /// <returns>an instance of HierarchyDataItem&lt;T&gt;</returns>
            public IHierarchyData GetHierarchyData(object enumeratedItem)
            {
                return new HierarchyDataItem<T>(
                    enumeratedItem as T,
                    this.ChildSelector,
                    this.ParentSelector,
                    this.PathSelector);
            }

            #endregion
        }
    }
}

I'm wrapping all of it in a static class: the public static method allows me to infer the generic type parameters.

Here's how you use it:

// The root node for my folder structure
var root = Folders.GetRoot();

// Setting the delegates for getting
// children, parent and path value
var folderData = HierarchyData.GetData(
    root, 
    d => d.SubFolders, 
    d => d.ParentFolder, 
    d => d.Name);

tree = new TreeView();

this.Controls.Add(tree);

if (!this.Page.IsPostBack)
{
    // now just assign datasource and bindings
    tree.DataSource = folderData;
    tree.DataBindings.Add(new TreeNodeBinding()
    {
        TextField = "Name",
        ValueField = "Key"
    });
    tree.DataBind();
}

And here's the download link: http://www.tabeoka.be/downloads/HierarchyData.zip .

I hope this helps someone, somewhere. I welcome comments and criticism.

Menno