I came across some interesting behaviour with the ASP.NET MVC 2 Beta yesterday. When I was binding to a DateTime value it would work fine with a POST request but when I switched that to a GET request, everything bombed. Weird.
After a bit more investigation I found it had to do with my culture... well, rather it had to do with theĀ GET request binding my date (formatted as 'dd/mm/yyyy') using the backwards American date format of 'mm/dd/yyyy' (flame on).
It was late at night at the time, so I quickly whipped up a very basic ASP.NET MVC application to reproduce the interesting behaviour I was experiencing and fired it off to Phil Haack - which in hindsight wasn't probably the best route to take, should've followed some sort of procedure and posted it to codeplex project's issue tracker instead of bothering Phil.
Anyway... after a good nights sleep, a good day at work under my belt and no reply from Phil (obviously a busy man and bigger things to worry about), I decided to have a gander at the issue myself.
After a short time of debuging into the ASP.NET MVC 2 Beta source code, I managed to find the culprit. Surprisingly the issue resided in the QueryStringValueProvider class - I know, who would've guessed?!
What I found is the following in all its undisguised glory:
// QueryString should use the invariant culture since it's part of the URL, and the URL should be
// interpreted in a uniform fashion regardless of the origin of a particular request.
protected override CultureInfo GetCulture(ControllerContext controllerContext) {
return CultureInfo.InvariantCulture;
}
My first thought was 'hang on, so this weird behaviour is actually intentional? WTF were they thinking?!?'. Then, naturally, images of a CultureAwareQueryStringValueProvider swirlled around my head - easy 'fix' I thought. But as my testosterone levels started to drop back to normal, I realised that someone smarter than me has obviously made a very conscience decision to make it culture unaware...
So why is it culture unaware?
Well, if you think about it, a URL is a pointer to a specific resource. So if the url is culture aware, that same URL could point to different resources.
E.g. say there was a URL like:
'http://www.temp.com/events?from=01/01/2010&to=01/03/2010&page=3'
If it was culture aware, my culture would expect it to show the 3rd page of events between 1st Jan 2010 & 1st March 2010 BUT someone else's inferior culture (flame stoke) might expect it to show the 3rd page of events between 1st Jan 2010 & 3rd Jan 2010.
Making sense now? Good.
So what are my options to fix this? Well, as I see it, there are 3 obvious solutions.
Option 1: Use a POST request instead of a GET request. This really isn't an option, in my situation I really need it to be a GET request.
Option 2: Create a custom binding to make the querystring culture aware. This really isn't an option because as I outlined above, URLs shouldn't be culture aware.
Option 3: Change the date format in the querystring. I.e. use the 'yyyy/mm/dd' format so that all cultures will understand and interpret the URL the same1. This is really the only option for me and I'm relatively happy with it... from a technical perspective it's super but from a usability perspective (e.g. users having to enter dates in that format), it may not be the best.
Any other ideas dear reader?
EDIT: Got a reply from Phil and he basically backed up my understanding of the situation and gave his take on some solutions similar to those outlined above. Cheers Phil! :-)
1If someone tells me that some culture recognises the date format 'yyyy/dd/mm' I'll probably cry. Seriously.