Change culture before ModelBinder is used
Asked Answered
L

3

11

I want to create a website in different languages. I already read that I could create an ActionFilter, but I have a litte problem:
I had to create a custom ModelBinder in order to work with english and german number formats (123,456,789.1 vs. 123.456.789,1)

public class DecimalModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        string key = bindingContext.ModelName;
        var v = ((string[])bindingContext.ValueProvider.GetValue(key).RawValue)[0];
        float outPut;
        if (float.TryParse(v, NumberStyles.Number, System.Globalization.CultureInfo.CurrentCulture, out outPut))
            return outPut;
        return base.BindModel(controllerContext, bindingContext);

    }
}

This ModelBinder uses the current culture to decide which format is used. But unfortunatly, the ModelBinder is used before the ActionFilter could change the culture.

How can I change the culture before the ModelBinder becomes active?

Latimore answered 18/11, 2012 at 22:28 Comment(0)
L
7

You can implement an IHttpModule and set the culture in the BeginRequest, as seen here.

void context_BeginRequest(object sender, EventArgs e)
{
    // eat the cookie (if any) and set the culture
    if (HttpContext.Current.Request.Cookies["lang"] != null)
    {
        HttpCookie cookie = HttpContext.Current.Request.Cookies["lang"];
        string lang = cookie.Value;
        var culture = new System.Globalization.CultureInfo(lang);
        Thread.CurrentThread.CurrentCulture = culture;
        Thread.CurrentThread.CurrentUICulture = culture;
    }
}
Lashondalashonde answered 18/11, 2012 at 22:40 Comment(3)
It's working, thank you a lot! But I have one question: Do you know, why the code is executed 5 times per request?Latimore
I'm not getting that behavior. Can you add a watch to ((System.Web.HttpApplication)(sender)).Request.RawUrl and see if the requests are the same?Lashondalashonde
@Latimore The code is executed once per request (hence the name BeginRequest) so perhaps there is one request for the page, and 4 more for stylesheets, images or JavaScript files. Check the Request.Url, which may shed some light.Popple
G
7

I usually set the CurrentCulture and CurrentUICulture by handling the PreRequestHandlerExecute event in Global.asax.cs (you could also handle this event in an IHttpModule as suggested by barry).

The point is to do this in an event that takes place before the model binding takes place. There are several other events that takes place before this one which you could utilize.

Look at the HttpApplication Class for information about available events, and the order in which they are raised.

    public class MvcApplication : HttpApplication
    {
        protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            var culture = new CultureInfo("en-GB"); // Get the culture name from the route values / request querystring / form / cookie
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = culture;
        }
    }

You could also do it by handling the OnActionExecuting event on your Controller (you probably want to create a base controller and do it there, then have all your controllers inherit from this base controller).

    public class MyBaseController : Controller
    {
        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var culture = new CultureInfo("en-GB"); // Get the culture name from the route values / request querystring / form / cookie
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = culture;

            base.OnActionExecuting(filterContext);
        }
    }

    public class MyController : MyBaseController
    {
        public ActionResult Index()
        {
            return View();
        }
    }
Gradualism answered 21/11, 2012 at 14:20 Comment(1)
-1: OnActionExecuting is invoked AFTER the model binder is invoked. So OnActionExecuting is too late.Conduce
C
4

Instances of IAuthorizationFilter get executed before model binding, thus allowing you to set the needed cultures

Chapiter answered 15/1, 2015 at 15:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.