Best place to set CurrentCulture for multilingual ASP.NET MVC web applications

后端 未结 5 1771
死守一世寂寞
死守一世寂寞 2020-11-28 07:22

For multilingual ASP.NET MVC 3 web application, I am determining the Thread.CurrentThread.CurrentCulture and Thread.CurrentThread.CurrentUICulture

相关标签:
5条回答
  • 2020-11-28 07:48

    Instead of overriding OnActionExecuting you can override Initialize here like this

    protected override void Initialize(RequestContext requestContext)
    {
            string culture = null;
            var request = requestContext.HttpContext.Request;
            string cultureName = null;
    
            // Attempt to read the culture cookie from Request
            HttpCookie cultureCookie = request.Cookies["_culture"];
            if (cultureCookie != null)
                cultureName = cultureCookie.Value;
            else
                cultureName = request.UserLanguages[0]; // obtain it from HTTP header AcceptLanguages
    
            // Validate culture name
            cultureName = CultureHelper.GetValidCulture(cultureName); // This is safe
    
            if (request.QueryString.AllKeys.Contains("culture"))
            {
                culture = request.QueryString["culture"];
            }
            else
            {
                culture = cultureName;
            }
    
            Uitlity.CurrentUICulture = culture;
    
            base.Initialize(requestContext);
        }
    
    0 讨论(0)
  • 2020-11-28 07:55

    I know an anser has already been selected. The option we used was to just Initialize the thread current culture in the OnBeginRequest event for the Application. This ensures the culture is discovered with every request

    public void OnBeginRequest(object sender, EventArgs e)
    {
       var culture = YourMethodForDiscoveringCulutreUsingCookie();
       System.Threading.Thread.CurrentThread.CurrentCulture = culture;
       System.Threading.Thread.CurrentThread.CurrentUICulture = culture;
    }
    
    0 讨论(0)
  • 2020-11-28 08:05

    I used a global ActionFilter for this, but recently I realized, that setting the current culture in the OnActionExecuting method is too late in some cases. For example, when model after POST request comes to the controller, ASP.NET MVC creates a metadata for model. It occurs before any actions get executed. As a result, DisplayName attribute values, and other Data Annotations stuff are handled using the default culture at this point.

    Eventually I've moved setting the current culture to the custom IControllerActivator implementation, and it works like a charm. I suppose it's almost the same from the request lifecycle perspective to host this logic in the custom controller factory, like you have today. It's much more reliable, than usage of global ActionFilter.

    CultureAwareControllerActivator.cs:

    public class CultureAwareControllerActivator: IControllerActivator
    {
        public IController Create(RequestContext requestContext, Type controllerType)
        {
            //Get the {language} parameter in the RouteData
            string language = requestContext.RouteData.Values["language"] == null ?
                "tr" : requestContext.RouteData.Values["language"].ToString();
    
            //Get the culture info of the language code
            CultureInfo culture = CultureInfo.GetCultureInfo(language);
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = culture;
    
            return DependencyResolver.Current.GetService(controllerType) as IController;
        }
    }
    

    Global.asax.cs:

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            ...
            ControllerBuilder.Current.SetControllerFactory(new DefaultControllerFactory(new CultureAwareControllerActivator()));
        }
    }
    
    0 讨论(0)
  • 2020-11-28 08:07

    If you don't use ControllerActivator, can use BaseController class and inhеrid from it.

    public class BaseController : Controller
    {
        public BaseController()
        {
              //Set CurrentCulture and CurrentUICulture of the thread
        }
    }
    

    public class HomeController: BaseController    
    {
        [HttpGet]
        public ActionResult Index()
        {
            //..............................................
        }
    }
    
    0 讨论(0)
  • 2020-11-28 08:09

    An alternative place to put this would be to put that code in the OnActionExecuting method of a custom ActionFilter, which can be registered in the GlobalFilters collection:

    http://weblogs.asp.net/gunnarpeipman/archive/2010/08/15/asp-net-mvc-3-global-action-filters.aspx

    0 讨论(0)
提交回复
热议问题