Melvyn Harbour

Software Developer living in Cambridge, England and working for Red Gate

MVC ModelBinder and Localization

One of the great things about the way in which the Microsoft ASP.NET MVC Framework is being developed is the fact that the team are publishing the source code as they go along. This makes it very simple to dig into the framework when something slightly surprising is happening and figure out exactly how it is supposed to work. A good example of this cropped up for us yesterday when looking at a form posting scenario using DateTimes. We were dealing with an Action Method that looked something like this:

   1: public ActionResult DoSomething(DateTime theDate)
   2: {
   3:     return View();
   4: }

And using the automatic model binding infrastructure to set the method parameter from a form. Naturally, being based in England, we were not totally shocked when we ran into localization issues almost immediately with this. It appeared at first glance that the date was being parsed assuming en-US format (mm/dd/yyyy), whereas for the application we were writing, which will be used internally be people who will expect to use en-GB (dd/mm/yyyy), we wanted it to parse in a different format. This prompted some investigation to discover what the framework was using to make its decision about which culture to use. The result turned out to be somewhat more clever than we had first thought, and nicely illustrates the way in which MVC Framework applications should be structured.

The initially surprising piece of information that it transpires that it actually matters whether you have set the HTTP method to be a GET or a POST. To understand why this is the case, here is a snippet from within the MVC source code. I have removed several lines from the code to make it easier to see what is going on. If you want to see the original, it is within GetValue(string name) of System.Web.Mvc.DefaultValueProvider.

   1: CultureInfo culture = CultureInfo.InvariantCulture;
   2:  
   3: if (request.QueryString != null)
   4: {
   5:     rawValue = request.QueryString.GetValues(name);
   6: }
   7: if (rawValue == null && request.Form != null)
   8: {
   9:     culture = CultureInfo.CurrentCulture;
  10:     rawValue = request.Form.GetValues(name);
  11: }

In other words, when looking for the value to parse, the framework looks in a specific order namely:

  1. RouteData (not shown above)
  2. URI query string
  3. Request form

Only the last of these will be culture aware however. There is a very good reason for this, from a localization perspective. Imagine that I have written a web application showing airline flight information that I publish online. I look up flights on a certain date by clicking on a link for that day (perhaps something like http://www.melsflighttimes.com/Flights/2008-11-21), and then want to email that link to my colleague in the US. The only way that we could guarantee that we will both be looking at the same page of data is if the InvariantCulture is used. By contrast, if I'm using a form to book my flight, everything is happening in a tight cycle. The data can respect the CurrentCulture when it is written to the form, and so needs to respect it when coming back from the form.

But this brings us back to a consideration of the HTTP method that has been used. Remember that if we set the form to be HTTP GET, when the form is submitted the values of the fields in the form will be turned into a query string. So they will be parsed with the InvariantCulture rather than the CurrentCulture, as they would have been if it were an HTTP POST. We can therefore toggle the behaviour of the form (from a localization standpoint) by changing the HTTP method.

Now to me this seemed slightly surprising at first, but I can certainly see that from the framework authors' perspective, it's the correct way of doing things. It still does leave one loose end, from a technical perspective. Suppose now that out airline flight information application allows the user to type in a date for which they wish to view flight information rather than clicking on a (computer generated) hyperlink. This is not an unreasonable behaviour, and is probably far more realistic of the way that the application would in fact be written. I still want the form to submit via HTTP GET rather than POST, as I want a URL to be generated that my user could email to his colleague. Effectively therefore, I have mandated that the user needs to enter the date using the InvariantCulture, which is hardly very localization friendly! If the application is only going to be used by people in (for example) en-GB (as might be the case for a company internal application), it is very possible that the date format will be known, and specified.

Help is at hand though! Luckily, the way that the MVC Framework has been written makes it very easy for us to drop in other components to ensure that specific parts of the application such as this run the way that we expect them to. In this instance, what we want to do is register a new ModelBinder that will handle this DateTime to parse it using a specified culture. Writing a new ModelBinder is actually staggeringly simple. All we need to do is implement IModelBinder, and then register the new ModelBinder in Global.asax.cs. A very simple example of a custom ModelBinder to force the binding of DateTimes to always use en-GB is given below.

   1: public class MyBinder : IModelBinder
   2: {
   3:  
   4:     #region IModelBinder Members
   5:  
   6:     public ModelBinderResult BindModel(ModelBindingContext bindingContext)
   7:     {
   8:         string theDate = bindingContext.HttpContext.Request.QueryString["theDate"];
   9:         DateTime dt = new DateTime();
  10:         bool success = DateTime.TryParse(theDate, CultureInfo.GetCultureInfo("en-GB"), DateTimeStyles.None, out dt);
  11:         if (success)
  12:         {
  13:             return new ModelBinderResult(dt);
  14:         }
  15:         else
  16:         {
  17:             // Return an appropriate default
  18:         }
  19:     }
  20:  
  21:     #endregion
  22: }

We then just need to tell MVC to use the ModelBinder. All this takes is a line in Global.asax saying:

   1: ModelBinders.Binders.Add(typeof(DateTime), new MyModelBinder());

Of course the custom ModelBinder could be modified to do anything else that you want to, or indeed descend from DefaultModelBinder, and use other properties of the binding to help it determine whether it should use the new behaviour, or leave it up to the original DefaultModelBinder. The above example isn't particularly realistic in that we have mandated that the value of a DateTime will be coming in on a query string parameter of 'theDate'. It would normally be the case that we would use other properties of the ModelBindingContext to be more accurate about the situations we need to override. The ModelBinder could also be specified explicitly using an attribute on the method parameter.

On a side note, I thought it would be worth linking to an article featuring Red Gate's biggest fan!

Posted: Nov 21 2008, 11:13 AM by MelvynHarbour | with 31 comment(s)
Filed under: ,

Comments

ASP.NET MVC Archived Blog Posts, Page 1 said:

Pingback from  ASP.NET MVC Archived Blog Posts, Page 1

# November 21, 2008 10:16 AM

Richard Kimber said:

Hi,

Thought you might be interested in my version (bound to DateTime?). I'm not sure I entirely agree with the reasons for ignoring the culture in the query string. As far as I concerned, the culture constitutes part of the contract between the client and server. If I was using a US site, I'd expect to use the US format, however odd I think it is :)

I haven't explicitly defined the culture as I have it set in the web.config.

public class UKDateTimeModelBinder : IModelBinder {

   public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {

       var date = bindingContext.ValueProvider[bindingContext.ModelName].AttemptedValue;

       if (String.IsNullOrEmpty(date))

           return null;

       bindingContext.ModelState.SetModelValue(bindingContext.ModelName, bindingContext.ValueProvider[bindingContext.ModelName]);

       try {

           return DateTime.Parse(date);

       }

       catch (Exception) {

           bindingContext.ModelState.AddModelError(bindingContext.ModelName, String.Format("\"{0}\" is invalid.", bindingContext.ModelName));

           return null;

       }

   }

}

# August 27, 2009 5:41 AM

escort incall London said:

It was rather interesting for me to read this post. Thanks for it. I like such themes and anything that is connected to this matter. I definitely want to read a bit more soon.

Joan Kuree

# May 16, 2010 7:52 AM

Gregor Suttie said:

Hi Melvyn

I wanted to use this code - what using statements did you have to use for this class?

Thanks

Gregor

# May 29, 2010 1:58 PM

indian escort east london said:

Pretty great article to pay attention to to my thinking. The only question I have, why don't you send that article to social bookmarks? This should bring rather big traffic to this page.

# May 29, 2010 5:58 PM

companionship said:

Really interesting domain to track it to my thinking. I have a question, why haven't you you submit that article to social media? That can bring lots of traffic to this article.

# June 15, 2010 11:42 PM

brunette college girls said:

Undoubtfully cool story you got here. It would be nice to read more concerning such matter. Thanx for giving that information.

Mia MOORE

# June 22, 2010 12:52 AM

exclusive escorts said:

It was rather interesting for me to read the article. Thanx for it. I like such themes and everything connected to this matter. I would like to read a bit more soon. BTW, pretty good design your site has, but don’t you think design should be changed once in a few months?

Kate Stone

# July 12, 2010 6:01 PM

wolfet said:

A very well written article, although I needed to read it twice to take it all in.

# July 19, 2010 8:06 PM

London escorts latin said:

I would like to read more soon. By the way, rather nice design that site has, but how about changing it once in a few months?

Chloe Globby

# July 27, 2010 4:50 AM

London brunette said:

It is extremely interesting for me to read that blog. Thanx for it. I like such themes and anything connected to them. I would like to read more soon.

Julia Benedict

# July 28, 2010 8:54 PM

Hilary Hakkinen said:

Rather nice blog you've got here. Thanx for it. I like such themes and anything that is connected to this matter. I would like to read a bit more soon.

Hilary Hakkinen

<a href="escorttweets.com/">european escort</a>

# September 21, 2010 11:27 PM

Kate Simpson said:

Pretty nice blog you've got here. Thanks for it. I like such themes and everything connected to this matter. I definitely want to read more on that blog soon.

Kate Simpson

<a href="kievcityescort.com/">escort girls kiev</a>

# September 26, 2010 5:02 PM

Donne said:

CHD is more common and is seen at earlier ages in individuals with SCI than it is in persons without SCI; this is likely associated with the higher incidence of metabolic syndrome (obesity, dyslipidemia, hypertension, insulin resistance, increased prothrombotic and pro-inflammatory states) in the former group.21,22,23  Abnormal lipid profiles, such as an elevation of total cholesterol (TC) and of low-density lipoprotein cholesterol (LDL-C), as well as a decrease in high-density lipoprotein cholesterol (HDL-C) levels, are not uncommon with chronic SCI and increase the risk for cardiovascular disease.24

# October 6, 2010 5:43 PM

Avril Benedict said:

It is certainly interesting for me to read the article. Thanx for it. I like such topics and anything that is connected to this matter. I would like to read more on that blog soon.

Avril Benedict

<a href="irelandescortdirectory.com/.../cork-escorts">escorts ireland cork</a>

# October 12, 2010 10:46 PM

plagiarism said:

Teacher, students, and publishers - all of you need http://bit.ly/bAuycP plagiarism detection service. Contact us today and get the peace of mind you deserve and need!

# November 6, 2010 11:49 AM

Katty Karver said:

Wow, rather nice information. How will I get that subscription?

Katty  Karver

<a href="www.wirelesscameradetectors.com/">bug sweeping</a>

# November 24, 2010 9:13 AM

Hilary Swenson said:

Pretty nice blog you've got here. Thanx for it. I like such themes and anything that is connected to them. I would like to read more soon.

What  do you think about changing it from time to time?

Hilary Swenson

<a href="monacoescort.com/">monaco escorts</a>

# November 29, 2010 7:00 AM

Joan Simpson said:

Impressive page. Ready to read more.  

Joan Simpson    

<a href="parisescort.info/">escort girl paris</a>

# December 16, 2010 5:16 AM

Anete Benedict said:

It is extremely interesting for me to read this article. Thanks for it. I like such topics and everything connected to this matter. I would like to read a bit more on that blog soon.  

Anete Benedict  

<a href="nyescorts.net/">new york independent escorts</a>

# January 21, 2011 3:40 AM

Katty Stepman said:

It is rather interesting for me to read that blog. Thank author for it. I like such themes and anything that is connected to them. I definitely want to read a bit more on this blog soon.    

Katty  Stepman  

<a href="indianescortmodels.com/">indian escort models</a>

# February 18, 2011 3:59 PM

Katty Watcerson said:

It was rather interesting for me to read the blog. Thanks for it. I like such topics and everything connected to this matter. I would like to read more on that blog soon.      

Katty  Watcerson    

<a href="www.jammer-store.com/">jammer car</a>

# March 5, 2011 3:04 AM

Kate Karver said:

It was extremely interesting for me to read the post. Thanks for it. I like such themes and everything that is connected to them. I definitely want to read more soon.        

Kate  Karver      

<a href="rome-escort.info/">escort girls roma</a>

# March 17, 2011 5:01 AM

Whitny Stone said:

It was extremely interesting for me to read the article. Thanx for it. I like such themes and everything connected to them. I definitely want to read a bit more on that blog soon.        

Whitny  Stone        

<a href="www.phone-blocker.com/">a cell phone jammer</a>

# March 25, 2011 12:09 AM

Jane Karver said:

It is certainly interesting for me to read this blog. Thanx for it. I like such themes and anything that is connected to them. I definitely want to read a bit more soon.          

Jane  Karver          

<a href="milanescorts.com/">masha escort girl milano</a>

# April 9, 2011 10:51 AM

Jenny Trider said:

It is rather interesting for me to read this post. Thanx for it. I like such topics and everything that is connected to them. I definitely want to read a bit more soon.            

Jenny  Trider          

<a href="www.baccaratgirls.com/">escorts London 24 7</a>

# April 17, 2011 12:43 AM

Mary Kripke said:

It is rather interesting for me to read the blog. Thanks for it. I like such themes and everything connected to this matter. I would like to read a bit more soon.            

Mary  Kripke            

<a href="monacoescort.com/">escorts monaco</a>

# April 27, 2011 6:54 PM

Clint Chapman said:

Here's an updated version for MVC 3 that uses the current culture:

   class DateTimeModelBinder : IModelBinder

   {

       #region IModelBinder Members

       public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)

       {

           var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

           var date = value.ConvertTo(typeof(DateTime), CultureInfo.CurrentCulture);

           return date;

       }

       #endregion

   }

# May 14, 2011 12:15 PM

David said:

#Clint Chapman

Nice piece of code. I use IActionFilter to set the currentCulture and currentUICulture depending on the user. The thing is that IActionFilter methods executes after the modelbinding. Do you have a solution for this?

# July 7, 2011 5:36 AM

mariah said:

se puede completar el blanco?  

http://eru1.myftp.biz/  

koko

# August 18, 2011 6:19 PM

What formats does ASP.NET MVC expect for DateTime so that the model binding will work properly? - Programmers Goodies said:

Pingback from  What formats does ASP.NET MVC expect for DateTime so that the model binding will work properly? - Programmers Goodies

# September 19, 2011 1:46 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)