Session State Behaviour & Async Headaches

I was battling a little issue today surrounding an action method no longer being called asynchronously; the issue turned out to be related to some recent session-based code being added to our code base. In short, the minute session is detected in the underlying code, the ‘default’ behaviour for session state handling throws a monkey wrench in asynchronicity, regardless of the operation being performed on session data (i.e. writing to the session or just reading from the session). This, for me, turned into a performance headache.

There is an attribute that can be placed at controller level that states ‘I’m reading from session only, please continue to allow asynchronous operations’, which when used looks like this:

[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
public class TestController : Controller
{
          ……
}

However, if you want to implement a control mechanism at the action level you need to travel down the custom controller factory/attribute route. This post turned out to be a lifesaver: Session State Behaviour Per Action in ASP.NET MVC

In short, this setup enables you to set session state behaviour handling at the action level by adorning the target method with a custom attribute; bonza!

When inspecting this and underlying, base class, implementations you will most likely discover that it’s not immediately clear how to handle scenarios where overridden methods exist (where methods match by name but differ by signature). This, for me, caused several crunches into the dreaded AmbigiousMatchException.

The implementation below shows my modified override of the DefaultControllerFactory GetControllerSessionBehavior method that is designed to a) avoid exceptions and b) only try to ‘discover’ the attribute and apply custom session state behaviour handling where a single method is ‘matched’ (based on the supplied RequestContext). If the custom attribute is not found, or more than one method is found matching by name (or another error occurs) base logic kicks in and takes precedence:

        /// <summary>
        /// Public overridden method that looks at the controller/action method being called and attempts
        /// to see if a custom ActionSessionStateAttribute (determining how session state behaviour should work) is in play.
        /// If it is, return the custom attributes SessionStateBehaviour value via the Behaviour property, in all other instances
        /// refer to the base class for obtaining a SessionStateBehavior value (via base.GetControllerSessionBehavior).
        /// </summary>
        /// <param name="requestContext">The request context object (to get information about the action called).</param>
        /// <param name="controllerType">The controller type linked to this request (used in a reflection operation to access a MethodInfo object).</param>
        /// <returns>A SessionStateBehavior enumeration value (either dictacted by us based on ActionSessionStateAttribute usage or the base implementation).</returns>
        protected override SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType)
        {
            try
            {
                // At the time of writing base.GetControllerSessionBehavior just returns SessionStateBehaviour.Default but to make this robust we should just call
                // base.GetControllerSessionBehavior if the controllerType is null so any changes to the base behaviour in future are adhered to
                if (controllerType != null)
                {
                    // Defensive code to check the state of RouteData before proceeding
                    if (requestContext.RouteData != null
                        && requestContext.RouteData.Values != null
                        && requestContext.RouteData.Values["action"] != null)
                    {
                        // Attempt to find the MethodInfo type behind the action method requested. There is a limitation here (just because of what we are provided with) that
                        // this piece of custom attribute handling (for ActionSessionStateAttribute) can only be accurately determined if we find just one matching method
                        string actionName = requestContext.RouteData.Values["action"].ToString();
                        List<MethodInfo> controllerMatchingActionMethods = controllerType.GetMethods(BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance)
                            .Where(method => method.Name.Equals(actionName, StringComparison.InvariantCultureIgnoreCase)).ToList();

                        // In order to avoid ambiguous match exceptions (plus we don't have enough information about method parameter types to pick the correct method in the case
                        // where more than one match exists) I needed to rig this in such a way that it can only work where one matching method, by name, exists (works for our current use cases) 
                        if (controllerMatchingActionMethods != null && controllerMatchingActionMethods.Count == 1)
                        {
                            MethodInfo matchingActionMethod = controllerMatchingActionMethods.FirstOrDefault();

                            if (matchingActionMethod != null)
                            {
                                // Does the action method requested use the custom ActionSessionStateAttribute. If yes, we can return the SessionStateBehaviour specified by the
                                // developer who used the attribute. Otherwise, just fail over to base logic
                                ActionSessionStateAttribute actionSessionStateAttr =
                                    matchingActionMethod.GetCustomAttributes(typeof(ActionSessionStateAttribute), false)
                                        .OfType<ActionSessionStateAttribute>()
                                            .FirstOrDefault();

                                if (actionSessionStateAttr != null)
                                {
                                    return actionSessionStateAttr.Behaviour;
                                }
                            }                       
                        }
                    }
                }
            }
            catch
            {
                // If any issues occur with our custom SessionStateBehavior inferring handling we're best to just let the base method calculate this instead (best efforts 
                // have been made to avoid exceptions where possible). Could consider logging here in future (but we're in an odd place in the MVC lifecycle, could cause
                // ourselves more issues by attempting this so will only do if absolutely required)
            }

            return base.GetControllerSessionBehavior(requestContext, controllerType);   
        }

This appeared to be a pretty robust solution in my case (and we gained back the asynchronous processing on the targetted methods = big plus), so, hopefully, this comes in handy for others at some point.

Cheers all!

Christmas Wind-down

Hi everyone,

With the holidays almost upon us I just wanted to wish everyone a very Merry Christmas and all the best for the New Year!

If possible, I will do my best to crank out a further post between now and the New Year. Here’s a teaser for the first part of the year (likely approximately the first quarter), taken from my original ‘pot of things’ to cover with a few additions that are taking precedence, based on current interests:

  • Continued prodding around in F# (likely starting with charting as promised).
  • The Razor View Engine (basic overview).
  • An Arduino starter project.
  • Deeper dives into JavaScript (in the build up to some exams…more to follow here).
  • As an extension to this, I want to do some ES6 coverage.
  • A return to Unity (I’ll probably do a big hit around the start of Spring).
  • Plus other things from my original cooking pot, including Udemy courses and sneak peaks on other libraries/utilities as I can, etc.

I may well revise my posting frequency a little also. After planning on doing two posts a week I’ve become acutely aware that I’m not really hitting that mark, so I’ll either go down to one post a week or learn to produce posts faster (and better!). We’ll have to see how all of this pans out.

Anyway, have a wonderful holiday!

Modernizr – Detecting Screen Size Changes

A brief titbit today, but one I felt was worth sharing and has come in handy for work/personal projects recently for me.

I’ve had a couple of requirements to gracefully show/hide and adjust web page layouts based on screen sizes (and screen re-sizing). I came across the following solution which works pretty damn well.

First things first, you’ll need Modernizr, which is in essence a feature detection javascript library. In this case, however, I’m using other features to react to browser re-sizing. There’s a few options for obtaining this for your projects but, as far as Visual Studio is concerned, I used the Package Manager Console using the following command:

Install Modernizr via the Package Manager Console.

Install Modernizr via the Package Manager Console.

Once installed, we end up with the javascript library included under the default Scripts folder:

Modernizr in Scripts Folder.

Modernizr in Scripts Folder.

On installing the package, as I didn’t specify a specific version, I end up with the following declaration in my packages.config file (part of my ASP.NET MVC project) – 2.8.3 denoting the most recent version:

<package id="Modernizr" version="2.8.3" targetFramework="net452" />

Next up, simply chuck the usual script element into your page to reference the library – Now you’re all set!

<script src="~/Scripts/modernizr-2.8.3.js" type="text/javascript"></script>

The following snippet shows the basic scaffolding code to start capturing screen size changes (I’ve declared this code in my jQuery document ready function). The doneResizing function is tied to the window resize event and you can easily use Modernizr to read and react to the screen size as required:

//Function to react to screen re-sizing
function doneResizing() {
	if (Modernizr.mq("screen and (min-width:868px)")) {
		//Implement jQuery/JS to handle a larger screen (i.e. Laptops/Desktops). In my case adding/removing a class to show/hide elements
	}
	else if (Modernizr.mq("screen and (max-width:867px)")) {
		//Implement jQuery/JS to handle a smaller screen (i.e. Tablets/Mobiles). In my case adding/removing a class to show/hide elements
	}
}

//Call doneResizing on re-size of the window
var id;
$(window).resize(function () {
	clearTimeout(id);
	id = setTimeout(doneResizing, 0);
});

//Call doneResizing on instantiation
doneResizing();

Currently, I’m using this to show/hide element containers within a web page based on screen size (and apply/remove a few classes on the fly to ensure everything looks as it should on desktop, tablet and mobile displays). It appears to function very well, one worth investigating for your own projects. See here for the original Stack Overflow article detailing ideas surrounding this concept (including other CSS related solutions).

Bye for now!