About your host

Photo of your host - Charles Vallance Charles Vallance is a web developer with a slight case of OCD when it comes to nice clean standards compliant html and code.

Badges

twitter / cvallance
My articles have been featured in The Morning Brew - Daily .NET News and Views

Tag Cloud

more tags...
posted @ Thursday, December 17, 2009 12:00 AM

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.

And then he said...

# re: ASP.NET MVC, DateTime Binding, and Culture Unaware URLs

Gravatar
Posted by Brian Milne
on 12/18/2009 9:23 AM
The Japanese!

And what's with those javascript hrefs?

# re: ASP.NET MVC, DateTime Binding, and Culture Unaware URLs

Gravatar
Posted by charles
on 12/18/2009 9:36 AM
Are you serious? I think you're lying and just trying to make me cry.

Javascript hrefs - don't know... something to do with the blog engine and it's rich text box editor I guess. I actually had to do it through the admin interface! Live Writer didn't want to install you see. Fixed now.

# re: ASP.NET MVC, DateTime Binding, and Culture Unaware URLs

Gravatar
Posted by Brian Milne
on 12/18/2009 9:54 AM
Many countries, according to the Wikipedia article "Calendar date" http://en.wikipedia.org/wiki/Calendar_date (No idea how to do links, javascript or not, in the comments), but a lot of it is "official" rather than "everyday" except maybe in East Asian countries such as Japan or Korea.

It is, of course the ISO standard, and makes sense on many levels. I've been trying to promote it's use wherever I can, but then again, you know me :)

# re: ASP.NET MVC, DateTime Binding, and Culture Unaware URLs

Gravatar
Posted by charles
on 12/18/2009 10:05 AM
Ah yes, we're on the same wave length... couldn't agree with you more.

I was going to cry if some culture used the format of 'yyyy/dd/mm' - huge spanner if some culture was like that.

# re: ASP.NET MVC, DateTime Binding, and Culture Unaware URLs

Gravatar
Posted by Brian Milne
on 12/18/2009 10:09 AM
OK, I misread that - I blame that good breakfast!

# re: ASP.NET MVC, DateTime Binding, and Culture Unaware URLs

Gravatar
Posted by kirill
on 12/18/2009 10:31 AM
en.wikipedia.org/.../Calendar_date

Iran, Kenya, Korea, South Africa...

Is that enough to make you cry?

# re: ASP.NET MVC, DateTime Binding, and Culture Unaware URLs

Gravatar
Posted by Charles
on 12/20/2009 11:58 AM
Kirill, kirill, kirill... your face needs to read the finer details of the format I would cry over. Note the 'dd' in the middle...? ;-)

# re: ASP.NET MVC, DateTime Binding, and Culture Unaware URLs

Gravatar
Posted by Liam Slater
on 6/17/2010 11:36 PM
Just come up against this problem myself (made even worse when I tried to make an action link using ToShortDateString and thus clashing cultures).

I get the fact that a url will need to be consistent to users regardless of their culture, but rather than the InvariantCulture surely allowing a culture set at the server would be a good solution. There is never going to be one acceptable dateformat so being able to aim your URLs at your main target (particularly as an intranet) is surely the best option.

# re: ASP.NET MVC, DateTime Binding, and Culture Unaware URLs

Gravatar
on 6/25/2010 11:34 PM
Regarding Visual Studio 2010 and .NET 4 support, that is unfortunately not a feasible option. The most recent public release of VS2010 and .NET 4 is Beta 2. However, our internal builds of MVC 2 for VS2010 and .NET 4 depend on features that were available only after Beta 2. In other words, if we released what we have right now for VS2010 and .NET 4 then it wouldn't even run....

# re: ASP.NET MVC, DateTime Binding, and Culture Unaware URLs

Gravatar
Posted by Ahmet
on 7/1/2010 5:34 AM
I define them as string params in action methods. If they are in objects, i exclude them using [bind(exclude="mydatevalue")] and define them as independent string params. I do the conversion manually in the action method and copy the value to the model if necessary.
I think that can be done with action filters too.

# re: ASP.NET MVC, DateTime Binding, and Culture Unaware URLs

Gravatar
Posted by BorisCallens
on 7/3/2010 7:49 AM
In my eyes it is the other way round. I think POSTs should use the InvariantCulture too.
Currently I have this issue: stackoverflow.com/.../cultureinfo-issue-with-mo...

Basically I'm POST-ing two doubles with a '.' as fraction separator and ModelBinding is trying to parse it with a ',' as a fraction separator..

Feel free to pitch in on the SO question..

And then I said...

Title *
Name *
Email
Url
Comment *  
Please add 1 and 2 and type the answer here: