Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC3 globalization: need global filter before model binding

Currently, I have a global filter called GlobalizationFilter that checks the route values, cookies and browser languages header to determine the correct culture settings for the request:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    // determine cultureInfo
    Thread.CurrentThread.CurrentCulture = cultureInfo;
    Thread.CurrentThread.CurrentUICulture = cultureInfo;
}

It all works, but the model binding process seems to occur before the global filters, and so the model binder doesn't take the culture settings into account.

This leads to problems with interpreting double values, DateTime values etc.

I could move the culture detection code to other locations, but I don't like any of my options:

  • Application's BeginRequest event. At this point of time the routing hasn't occurred, so I'll have to manually fish out the /en-US/ culture token from the URL. This in unacceptable.

  • Controller's Initialize() method. This will force me to write a base class for all my controllers, and inherit the existing controllers from it. I don't like this, but I'll opt for this solution if nothing better comes up.

Ideally, I want to find some way to inject my code between the "routing complete" and "model binding starts" events, but I found nothing in MSDN / Google on this.

Or maybe there's some other way to handle MVC3 globalization that I'm unaware of?

Thanks in advance for any contribution.

like image 947
Zruty Avatar asked Aug 26 '11 09:08

Zruty


1 Answers

Extract out the code that determines the culture into a separate component/class. Then create a ModelBinder that derives from DefaultModelBinder that uses the class to set the culture before calling BindModel

public class CultureAwareModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        /* code that determines the culture */
        var cultureInfo = CultureHelper.GetCulture(controllerContext.HttpContext);

        //set current thread culture
        Thread.CurrentThread.CurrentCulture = cultureInfo;
        Thread.CurrentThread.CurrentUICulture = cultureInfo;

        return base.BindModel(controllerContext, bindingContext);
    }
}

and then register it for the application (in Application_Start)

// register our own model binder as the default
ModelBinders.Binders.DefaultBinder = new CultureAwareModelBinder();
like image 51
Russ Cam Avatar answered Oct 18 '22 04:10

Russ Cam