views:

1874

answers:

4

What is the best place to set the Culture/UI Culture in an ASP.net MVC app

Currently I have a CultureController class which looks like this:

public class CultureController : Controller
    {
        public ActionResult SetSpanishCulture()
        {
            HttpContext.Session["culture"] = "es-ES";
            return RedirectToAction("Index", "Home");
        }

        public ActionResult SetFrenchCulture()
        {
            HttpContext.Session["culture"] = "fr-FR";
            return RedirectToAction("Index", "Home");
        }
    }

and a hyperlink for each language on the homepage with a link such as this

<li><%= Html.ActionLink("French", "SetFrenchCulture", "Culture")%></li>
<li><%= Html.ActionLink("Spanish", "SetSpanishCulture", "Culture")%></li>

Which works fine but I am thinking there is a more appropriate way to do this

I am reading the Culture using the following ActionFilter http://www.iansuttle.com/blog/post/ASPNET-MVC-Action-Filter-for-Localized-Sites.aspx

I am a bit of an MVC noob so am not co0nfident I am setting this in the correct place

I dont want to do it at the web.config level, it has to be based on a users choice.

I also dont want to check their http-headers to get the culture from their browser settings

Edit:

Just to be clear - I am not trying to deciede whether to use session or not. I am happy with that bit.

What I am trying to work out is if it is best to do this in a Culture controller that has an action method for each Culture to be set.

Or is there is a better place in the MVC pipeline to do this

anyone any ideas?

A: 

Being as it is a setting that is stored per-user, the session is an appropriate place to store the informtion.

I would change your controller to take the culture string as a parameter, rather than having a different action method for each potential culture. Adding a link to the page is easy, and you shouldn't need to write the same code repeatedly any time a new culture is required.

public class CultureController : Controller    
{
        public ActionResult SetCulture(string culture)
        {
            HttpContext.Session["culture"] = culture
            return RedirectToAction("Index", "Home");
        }        
}

<li><%= Html.ActionLink("French", "SetCulture", new {controller = "Culture", culture = "fr-FR"})%></li>
<li><%= Html.ActionLink("Spanish", "SetCulture", new {controller = "Culture", culture = "es-ES"})%></li>
NerdFury
thanks for the answer, I am not trying to deciede whether to use session or not. I am happy with that bit.What I am trying to work out is if it is best to do this in a Culture controller that has an action method for each Culture to be setOr is there is a better place in the MVC pipeline to do this
Christo Fur
I have provided an edited answer that better fits the question.
NerdFury
Yes, that is certainly cleaner, but what I really want to know is if this should be done in a Controller at all. Or if there is a better place in the MVC pipeline to set Culture. Or if it is better in an ActionFilters, Handlers, Modules etc
Christo Fur
A handler and module don't make sense because the user hasn't had a chance to make a selection. You need a way for the user to make a selection, and then process the users selection, that will be done in a controller.
NerdFury
agreed, handlers and modules are to early to allow user interaction. However, I am quite new to MVC so am unsure if this is the best place in the pipeline to set it. If I don't hear otherwise after a while I'll accept your answer.p.s. that syntax you have used to pass a parameter to an Action method doesnt seem to work. It doesnt have a controller defined so just uses the default one (which is not the correct one in this case). And there doesnt appear to be another overload suitable
Christo Fur
I made the change above regarding the ActionLink. You can specify the correct controller in the anonymous class.
NerdFury
+3  A: 

I would do it in the Initialize event of the controller like this...

    protected override void Initialize(System.Web.Routing.RequestContext requestContext)
    {
        base.Initialize(requestContext);

        const string culture = "en-US";
        CultureInfo ci = CultureInfo.GetCultureInfo(culture);

        Thread.CurrentThread.CurrentCulture = ci;
        Thread.CurrentThread.CurrentUICulture = ci;
    }
Jace Rhea
the culture string can't be a const, as the user needs to be able to specify the culture they would like to use on the site.
NerdFury
I understand that, but the question was where it was best to set the culture not how to set it.
Jace Rhea
+4  A: 

I'm using this localization method and added a route parameter that sets the culture and language whenever a user visits mysite.com/xx-xx/

example:

routes.MapRoute("DefaultLocalized",
            "{language}-{culture}/{controller}.aspx/{action}/{id}",
            new
            {
                controller = "Home",
                action = "Index",
                id = "",
                language = "nl",
                culture = "NL"
            });

I have a filter that does the actual culture/language setting:

public class InternationalizationAttribute : ActionFilterAttribute {


    public override void OnActionExecuting(ActionExecutingContext filterContext) {

        string language = (string)filterContext.RouteData.Values["language"] ?? "nl";
        string culture = (string)filterContext.RouteData.Values["culture"] ?? "NL";

        Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture));
        Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture));

    }
}

Now whenever a visitor goes to http://mysite.com/de-DE/Home/Index the German site is displayed.

I hope this answers points you in the right direction.

jao
In my opinion, using the URL to specify the language is the worst thing you can do. It totally violates REST and you're getting yourself in trouble if you ever want to add AJAX.
Dave Van den Eynde
Violates REST and trouble with AJAX? Why?
Eduardo Molteni
I also likes to put the lang in the URL, because it became crawlable by search engines in different languages and allow the user to save or send a URL with a specific lang.
Eduardo Molteni
Adding the language to the url does not violate REST. It fact it adheres to it by making the web resource not dependent on a hidden session state.
Jace Rhea
The web resource is not dependent on a hidden state, the way it's rendered is. If you want to access the resource as a web service, you'll need to choose a language to do it in.
Dave Van den Eynde
A: 

Hi!

Sorry for my poor english ... i set these codes on my asp.net mvc project and they "apparently" work, i mean they execute without errors, but there is no changes of culture on my ajax control toolkit calendar, it remains set in english!

Anyone?

Juliana Machado