asp.net-mvc - net - que es mvc 5
El mejor lugar para establecer CurrentCulture para aplicaciones web multilingües ASP.NET MVC (4)
Para la aplicación web multilingüe ASP.NET MVC 3, estoy determinando Thread.CurrentThread.CurrentCulture
y Thread.CurrentThread.CurrentUICulture
en la fábrica del controlador de la siguiente manera:
public class MyControllerFactory : DefaultControllerFactory {
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) {
//Get the {language} parameter in the RouteData
string UILanguage;
if (requestContext.RouteData.Values["language"] == null)
UILanguage = "tr";
else
UILanguage = requestContext.RouteData.Values["language"].ToString();
//Get the culture info of the language code
CultureInfo culture = CultureInfo.CreateSpecificCulture(UILanguage);
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
return base.GetControllerInstance(requestContext, controllerType);
}
}
¡El código anterior tiene casi un año ahora! Entonces, abro para sugerencias.
Y registro esto en el archivo Global.asax como:
ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
Esto está funcionando bien, pero no estoy seguro de si es la mejor práctica y el mejor lugar para realizar este tipo de acciones.
No he profundizado en la función principal de ControllerFactory
y no puedo compararla con ActionFilterAttribute
.
¿Qué opinas sobre el mejor lugar para realizar este tipo de acciones?
En lugar de anular OnActionExecuting
, puede anular Initialize
aquí como este
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);
}
Sé que un anser ya ha sido seleccionado. La opción que utilizamos fue simplemente Inicializar el cultivo actual de subprocesos en el evento OnBeginRequest para la Aplicación. Esto asegura que la cultura se descubra con cada solicitud
public void OnBeginRequest(object sender, EventArgs e)
{
var culture = YourMethodForDiscoveringCulutreUsingCookie();
System.Threading.Thread.CurrentThread.CurrentCulture = culture;
System.Threading.Thread.CurrentThread.CurrentUICulture = culture;
}
Un lugar alternativo para poner esto sería poner ese código en el método OnActionExecuting de un ActionFilter personalizado, que se puede registrar en la colección de GlobalFilters:
http://weblogs.asp.net/gunnarpeipman/archive/2010/08/15/asp-net-mvc-3-global-action-filters.aspx
ActionFilter
un ActionFilter
global para esto, pero recientemente me di cuenta de que la configuración de la cultura actual en el método OnActionExecuting
es demasiado tarde en algunos casos. Por ejemplo, cuando el modelo después de la solicitud POST llega al controlador, ASP.NET MVC crea un metadato para el modelo. Ocurre antes de que se ejecuten las acciones. Como resultado, los valores de los atributos DisplayName
y otras cosas de anotaciones de datos se manejan usando la cultura predeterminada en este momento.
Eventualmente me mudé configurando la cultura actual en la implementación personalizada IControllerActivator
, y funciona como un encanto. Supongo que es casi lo mismo desde la perspectiva del ciclo de vida de la solicitud alojar esta lógica en la fábrica de controladores personalizados, como lo hace hoy. Es mucho más confiable que el uso de ActionFilter
global.
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()));
}
}