Wednesday, July 31, 2013

manage static state in Global.asax.cs

Following upon this, I found myself wondering if static state will persist across the changing of "pages" in a stateless web application. It turns out that it will! If you have something like so managing a counter...

namespace MvcApplication.Models
{
   public static class Counter
   {
      public static int Count;
   }
}

 
 

...the counter will grow (without getting confused or resetting) as you switch back and forth between two actions in a controller (in an ASP.NET MVC4 Web API application with C# in this case) as seen here:

using System.Web.Mvc;
using MvcApplication.Models;
namespace MvcApplication.Controllers
{
   public class HomeController : Controller
   {
      public ActionResult Index()
      {
         return View(++Counter.Count);
      }
      
      public ActionResult About()
      {
         return View(++Counter.Count);
      }
   }
}

 
 

We can drive the upfront assignment of our counter from Global.asax.cs like so:

using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using MvcApplication.Models;
namespace MvcApplication
{
   public class WebApiApplication : System.Web.HttpApplication
   {
      protected void Application_Start()
      {
         Counter.Count = 0;
         AreaRegistration.RegisterAllAreas();
         WebApiConfig.Register(GlobalConfiguration.Configuration);
         FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
         RouteConfig.RegisterRoutes(RouteTable.Routes);
         BundleConfig.RegisterBundles(BundleTable.Bundles);
      }
   }
}

 
 

When I did this in Cassini I noticed that I could open two different browsers and the two browsers together would affect each other's counters and bias each others numbers. (They both dogpiled onto the counter.) Also, I noticed that if I closed all browsers, stopped the application, and restarted it, the the counter did not reset to zero. Only restarting Visual Studio allowed for a reset back to zero. This seemed imperfect so I tried this instead:

using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using MvcApplication.Models;
namespace MvcApplication
{
   public class WebApiApplication : System.Web.HttpApplication
   {
      protected void Application_Start()
      {
         AreaRegistration.RegisterAllAreas();
         WebApiConfig.Register(GlobalConfiguration.Configuration);
         FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
         RouteConfig.RegisterRoutes(RouteTable.Routes);
         BundleConfig.RegisterBundles(BundleTable.Bundles);
      }
      
      protected void Session_Start()
      {
         Counter.Count = 0;
      }
   }
}

 
 

Well, this got rid of the need to restart the application. I was able to just close all browsers to set the counter back to zero. However, different browsers still shared state! I then remembered I was using Cassini which only has one session. I switched to using IIS and the counter then only incremented based on browser session as desired!

No comments:

Post a Comment