Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.Net MVC resource files are sometimes incorrectly loaded by the ResouceManager

Overview

We have a multinational website which has localised content for the various countries it serves. This localisation is implemented using standard .Net resource files.

When our web application starts up or recycles under load on the production environment, sometimes it will display the wrong resources for a particular country. E.g. the UK site may show French content.

This continues to happen until the application is restarted.

Detail

The production environment is IIS 8 on Windows Server 2012. The application is implemented in ASP.Net MVC 4.

The application decides which locale it is serving by the incoming URL. So www.mysite.com will be UK English www.mysite.fr will be French etc.

We have an implementation of IHttpModule which is registered via a Web.config. In the Init method of the module, it attaches a handler to the BeginRequest event. In this method, the incoming URL is examined and the thread's CurrentUICulture is set to an appropriate value. en-GB for www.mysite.com, fr-FR for www.mysite.fr etc.

This system works well for the most part. However, sometimes when the application starts up while it is receiving requests, it will consistently serve the wrong content for some of the resource files.

It continues to do this until the application is restarted. It may again restart serving the incorrect content. We have to keep restarting until it is serving the correct content, at which point it will remain stable.

Analysis

We have been able to reproduce this locally on a development PC by throwing requests at the application during startup (using Fiddler). The site was showing German content for some resource files on the UK version of the site.

Having checked the obvious culprits in our code (that the CurrentUICulture is set correctly by the HTTP module and remains correct throughout the processing of the request), we started to look at the resource manager.

With the application started in this incorrect state, we examined the contents of the _resourceSets property on the ResourceManager class. This is a Dictionary keyed on the ISO culture code. Examining the contents of en-GB, we found that it did actually contain the resource strings from the German version of the resource file.

It seems that sometimes, when the site is starting up while receiving requests, the ResourceManager class is loading the wrong resource file for a culture or it is incorrectly classifying the file in its Dictionary.

Has anyone else experienced this kind of behavior and is anyone aware of any workarounds?

Thanks.

like image 842
Stevo Avatar asked Jul 15 '13 10:07

Stevo


3 Answers

This sounds like you are having thread safety problems in your handler. When you modify the threads current culture, you are modifying it for the current thread that could be processing multiple requests. When the responses are generated, another request could have altered the thread current language giving all responses the same language.

I have a few suggestions you can start off with:

  1. Make sure your handler is NOT reusable. I assume you've made implemented IHttpHandler, return false for the IsReusable property since multiple threads should hit it at the same time and a new instance will be created per request.
  2. Don't use a handler... A handler is not the ideal solution for something like this, The preferred place to set the thread culture is in Application_AcquireRequestState which will be correctly fired for each request without overlapping.
  3. Use a routing handler instead: http://adamyan.blogspot.com/2010/07/addition-to-aspnet-mvc-localization.html

Without seeing the handler you speak of the rest can only be speculation as to why responses are sharing thread cultures. The problem could easily lie in the dictionary you are using as well which is inherently not thread safe.

like image 101
BrutalDev Avatar answered Nov 14 '22 17:11

BrutalDev


We hit the same problem recently. This appears to be a race condition in ResourceManager (or its helper code). I've put together a repro at https://bitbucket.org/onyxmaster/resmanrc. Also, I filed a bug on MS Connect site, at https://connect.microsoft.com/VisualStudio/feedback/details/806505/.

P.S. I'm not sure if this counts as an answer since there is no workaround I know of, but at least now there is a repro and a bug report.

like image 21
onyXMaster Avatar answered Nov 14 '22 17:11

onyXMaster


For anyone else experiencing this problem, I never got a fix for the underlying cause of this problem, but did find a workaround. When the app starts up, I had a routine go through each resource file sequentially and request a resource from each file in each supported language. 'Touching' each file in this way in a single threaded manner seemed to allow all the resources to load correctly every time.

like image 1
Stevo Avatar answered Nov 14 '22 17:11

Stevo