Beware! ASP.NET MVC ActionFilterAttributes are cached between requests!

My colleagues and I recently encountered a very strange bug in an ASP.NET MVC web-site which seemed to be to do with NHibernate. The error suggested that we were trying to use a session that had already been closed. We could not find any sign of a closed session anywhere within the controllers in our project. Eventually we pinned the error down to a repository (containing an NHibernate session) referenced in an ActionFilterAttribute. The guy that wrote the code assumed that the repository would be referenced freshly by the attribute each time it was used, but of course it wasn’t; the .NET engine was helpfully caching the attribute between calls so that some users were getting sessions intended for other users.

The moral of the story is to make sure your ActionFilterAttributes are always stateless.

The following simple demonstration highlights this. Here is an ActionFilterAttribute which stores the date and time in a field on construction:

using System;
using System.Web.Mvc;

namespace WebTest.Attributes
{
    public class TestActionFilterAttribute : ActionFilterAttribute
    {
        private readonly DateTime _now;

        public TestActionFilterAttribute()
        {
            _now = DateTime.Now;
        }
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // Put the date into a ViewBag property:
            filterContext.Controller.ViewBag.DateTime = _now;
        }
    }
}

This is then used in a controller as follows:

using System;
using System.Text;
using System.Web.Mvc;
using WebTest.Attributes;

namespace WebTest.Controllers
{
    public class HomeController : Controller
    {
        [TestActionFilter]
        public ActionResult Index()
        {
            const string dateTimeFormat = "yyyy-MM-dd HH:mm:ss.fffffff";

            var text = new StringBuilder();

            text.AppendFormat("DateTime called directly: {0}<br/>", DateTime.Now.ToString(dateTimeFormat));
            text.AppendFormat("DateTime taken from ActionFilterAttribute: {0}<br/>", ViewBag.DateTime.ToString(dateTimeFormat));

            return Content(text.ToString());
        }
    }
}

If you refresh the page a few times you’ll notice that the time coming from the ViewBag (which originates from the attribute) remains the same while the current time continues to increase, proving that the attribute isn’t being instantiated for each web call. You have been warned!

Installing two build agents on TeamCity

Other than jogging my memory in the future when I need to do the same thing again, this post adds no value other than to direct people to Marcos Placona’s great blog post on how to run two build agents on the same TeamCity instance. Unfortunately this doesn’t work out of the box so there is some tweaking involved, as you’ll see.

So, without further ado, over to you Marcos…

http://www.placona.co.uk/1327/technology/new-teamcity-agents-the-right-way/

Granting folder/file access permissions to IIS AppPool users

By default, processes than run under IIS won’t have permission to access folders you create on your server hard drive. So, if you want your web-sites to interact with folders and files you’ll need add access permissions using the standard folder properties dialog:

Security Permissions Dialog

Permissions must be granted to the AppPool that your site uses. To grant permissions to AppPool users, the user name you enter in the Select Users or Groups dialog:

Select User or Group Dialog

…should match the following pattern:

IIS AppPool\[AppPool Name]

When you click Check Names the text you entered will magically detect the AppPool.

Keeping up with technology

It can sometimes be frightening how quickly the IT world changes. Almost every week something is released that promises to be the “next big thing” that will “revolutionise the way we develop applications”. A lot of my colleagues populate their “learn next” list by reading Twitter, but personally this approach doesn’t work for me as I don’t scroll through my feed very often, and when I do I’m not usually in a good place to start reading more about a new technology and delving into a “Hello World”.

Instead, a colleague recommended the ThoughtWorks Technology Radar. It’s updated about twice and year and suggests Techniques, Tools, Platforms and Languages & Frameworks to look into.

For me it was quite intimidating at first when I realised I didn’t recognise most of the things on the list, but even just finding out what each thing is can be extremely helpful when solving everyday IT problems. Not only that, but it solves the difficult problem of knowing which horses to back. There simply isn’t time to learn about every new bell and whistle on the market, but the Technology Radar helps by suggesting which tools to trial.

Thanks ThoughtWorks!