��� 
Handjob porn amateur sexpurchase synthroid freesex dildo videowww porno com porno ru

ASP.NET MVC, session state and concurrent requests: not what you’d expect September 28, 2010

Using ASP.NET’s session storage and management providers for web applications is a no-brainer. User’s preferences, external API access tokens, uploaded documents, you name it, it usually makes sense. We’ll move it into the database when it gets too big, right?

Our new photo book creation and printing service, Poyomi (a little tech intro) uses the session state via MVC’s wrapper class HttpSessionStateBase which is provider as the SessionData property on a MVC controller. We store pretty much everything before the finished photo book is assembled: cover design, book’s designed pages, photo assembly preferences, perhaps an access token for flickr or SmugMug…

Poyomi has to render many preview images for a client, doing it so asynchronously by offloading the rendering work to backend servers. A single page’s design and contained photos come from a serialized object in the session itself, that is then transferred via AMQP to the queue processor. All the MVC web app has to do is to wait for the response and pass it over to the client.

Since each photo book contains many pages, browsers will try to load images using multiple concurrent requests at the same time. That shouldn’t be a problem for the massively threaded queue processor and a simple MVC app, right?

Unfortunately, no. All of the little thumbnails were being loaded sequentially and the backend was doing just a single rendering job at a time. What was going on? I took a look at IIS’ requests page (IIS manager > Home > IIS section > Worker Processes > Right click on the Pool > View Current Requests).

IIS requests trace

Huh? A single request at a time. Talk about abysmal performance.

More consequences on typical ASP.NET MVC websites

AJAX requests often get used to offload time intensive operations. In case all of your HTTP requests, AJAX or not, demand the usage of the session data, they will all block each other. In case the user decides to “cancel” the current background operation by clicking on a link to another page on your site, the execution of it will be delayed until all of the existing requests finish processing.

ASP.NET’s session state

Digging and debugging revealed that it all has to do with the way ASP.NET handles session access. You can read about it more at MSDN.

By default, no concurrent access to the session state is allowed. Even read-only requests (as far as the session is concerned) will be locked exclusively to prevent potential corruption of its state. There is a global or per-ASPX-page setting called EnableSessionState to alter this behavior: either by disabling the session state altogether… which isn’t really useful in our case… or by marking certain pages as being read-only and thus enabling parallel execution of read-only requests. Yay! But what about our cool and modern ASP.NET MVC 2 application?

Well, it can be done. But doing so requires a visit to the MvcFutures department. I’ve found a single lone blog post that describes the required changes to your MVC execution flow – presumably by a coworker of the one that programmed the solution. Essentially, it implements a new controller factory that is able to set the session state mode per the controller being executed.

Setting the session state mode in ASP.NET MVC 2

  1. Download the MvcFutures library. Add a local reference to the Microsoft.Web.Mvc.dll library.
  2. Add the module into your project’s Web.config to load the dynamic session controller factory. Add the highlighted lines:

    <httpModules>
      <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>  
      <add name="MvcDynamicSessionModule" type="Microsoft.Web.Mvc.MvcDynamicSessionModule, Microsoft.Web.Mvc, Version=2.0.0.0"/>
    </httpModules>
    <modules runAllManagedModulesForAllRequests="true">
        <remove name="ScriptModule"/>
        <remove name="UrlRoutingModule"/>
        <add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> 
        <add name="MvcDynamicSessionModule" type="Microsoft.Web.Mvc.MvcDynamicSessionModule, Microsoft.Web.Mvc, Version=2.0.0.0"/>
    </modules>
    

    Add this module after the routing module.

  3. Tell MVC to use the new dynamic session controller factory by instantiating and assigning it in your Global.asax.cs file:

    protected void Application_Start() {
        AreaRegistration.RegisterAllAreas();
        RegisterRoutes(RouteTable.Routes);
        ControllerBuilder.Current.SetControllerFactory(new MvcDynamicSessionControllerFactory());
    }
    
  4. Use the session state attribute on your controller:

      [ControllerSessionState(ControllerSessionState.ReadOnly)]
      public class AjaxReadonlyController : Controller {
    

    Other state modes are: Required (equivalent to Default), ReadOnly and Disabled.

Enjoy your high-performance website!

Using Autofac with DynamicSessionControllerFactory

If you are using Autofac for dependency injection (and why aren’t you?) you’ll have to nest the two controller factories. Global.asax.csApplication_Start:

var factory = new AutofacControllerFactory(ContainerProvider);
var dyn = new MvcDynamicSessionControllerFactory(factory);
ControllerBuilder.Current.SetControllerFactory(dyn);

Also, be warned that you cannot inject the session data object into your classes anymore. For example, if you were using something akin to:

var builder = new ContainerBuilder();
builder.Register(s => HttpContext.Current.Session).As().HttpRequestScoped();

…then this won’t work anymore. The controller’s SessionData property is null until MVC gets around to executing your method. You’ll have to pass it to instances that were already instantiated by Autofac’s controller factory at execution time.

In conclusion

I’m sure that almost every MVC project uses the session for storage of little tokens, strings, counters… which by default blocks the execution of parallel requests. Surprisingly, almost no one blogged about this before. Hopefully this article will add some exposure to this problem.

All of this applies to ASP.NET MVC 2, the latest production ready version. Please let me know if this is going to be implemented in MVC 3 without the usage of MvcFutures!

7 Comments
Craig Stuntz September 28th, 2010

“…perhaps an access token for flickr or SmugMug…”

Be really careful about this. Session is not directly connected to authorization, and is not secure by default. (Google “ASP.NET session hijacking.”) Security-sensitive data should generally not be stored there.

Manu Temmerman-Uyttenbroeck September 29th, 2010

We bumped into the same 2 weeks ago. But then for a “normal” ASP.NET webforms application.
We got around it and it significantly boosted the performance!

We basically now have only have 1 aspx page that has enabled session state. It’s the page that’s used to log in; so the first page the user has to visit to be able to use the web application.
After there are made http requests to other aspx pages and web services. All of those other pages / services now have session state disabled.

But how can we still store session stuff then? We made a “custom session cache” that uses the session id as key. When the user surfs to the login page, ASP.NET generates the ASP.NET_SessionId cookie (name can be changed in web.config). In all those other pages / services we’re able to retrieve the value of that cookie and find the correct cached data in our custom session cache.
Each aspx / asmx request runs some code which stores the “last activity” datetime in the users session cache. When the application starts, we start a thread that checks which sessions were not active for a period longer then the session timeout. That allows us to clean up the custom session cache.

Something like that :)

[...] ASP.NET MVC, session state and concurrent requests: not what you’d expect – ‘Rudi’ explores some performance problems in an ASP.NET application, discovering a bottle neck in the application caused by Session State, resulting in only a single request from a user executing at the same time. Rudi then explores techniques for improving this in ASP.NET and ASP.NET MVC applications. [...]

Nicholas van Esch February 16th, 2011

Is it possible to use the MVC 3 style solution of ControllerSessionState(ControllerSessionState.ReadOnly)] with a MVC 1 site?

obviously like your web-site however you need to take a look
at the spelling on quite a few of your posts. Many of them are rife
with spelling problems and I find it very bothersome to tell
the reality on the other hand I’ll certainly come back again.

kampen April 9th, 2013

erwo było błogie, siarκa nаtοmiast salеtra co wіęcej
kampen
ѕpośróԁ hufnalami wаżуły skromniеj
niżeli prawdziωe owcze bebechy. Odmiennej

drogocеnny, wyjąwszy innej na krzyż krzaki, nie ѕtało.
Zbrojni obstawiаli szczelnie smoсzą pieczarę,

whatsapp May 3rd, 2013

Hey, I think your site might be having browser compatibility issues.
When I look at your blog in Opera, it looks fine but when
opening in Internet Explorer, it has some overlapping.

I just wanted to give you a quick heads up! Other
then that, excellent blog!

Leave a Reply

 
Order diflucan no prescription. Purchase promethazine no prescription. Buy valacyclovir 1000mg online with no prescription.