最适合覆盖 mvc 基本控制器以设置文化的方法
Most suitable method to override on mvc base controller for setting culture
我的 mvc 应用程序中有一个基本控制器,所有控制器都继承自该控制器。基本控制器继承 System.Web.Mvc
命名空间中的抽象 class 控制器,我需要在每个控制器操作上设置文化。我可以重写许多方法,例如 OnActionExecuting, Initialize, ExecuteCore, BeginExecute
考虑绩效哪一个最适合这份工作? (以上 4 种方法只是示例,完整列表参见 MSDN)
我们实施了一种根据用户 Accept-Language header 改变文化的方法,但也允许他们自己明确设置,我们问自己同样的问题。
我们发现 Initialize 方法是设置它的最佳位置,因为它在其他方法之前和任何操作过滤器之前被调用。这对我们很重要,因为我们希望动作过滤器能够尊重预期的文化。
我不确定在每种方法中设置文化是否会有任何性能差异。我相信它们只会在不同的时间点执行,即在操作过滤器之前、模型绑定之前和临时数据加载之后等。
我相信我们在源代码库的某个地方有一个助手 class 可以概述我们是如何做到的。让我知道你是否喜欢这个,我会把它挖出来。
抱歉,我知道你的问题更具体,我只是想分享我的经验。
更新
这里要求的是我们用过的助手class
public class GlobalisationCookie
{
public GlobalisationCookie(HttpRequestBase request, HttpResponseBase response)
{
_request = request;
_response = response;
}
private readonly HttpRequestBase _request;
private readonly HttpResponseBase _response;
//
// Gets a collection of users languages from the Accept-Language header in their request
//
private String[] UserLanguges
{
get
{
return _request.UserLanguages;
}
}
//
// A dictionary of cultures the application supports - We point this to a custom webconfig section
// This collection is in order of priority
public readonly Dictionary<string, string> SupportedCultures = new Dictionary<string, string>() { { "en-GB", "English - British" }, { "no", "Norwegian"} }
//
// Summary:
// reads the first part of the culture i.e "en", "es"
//
private string GetNeutralCulture(string name)
{
if (!name.Contains("-")) return name;
return name.Split('-')[0];
}
//
// Summary:
// returns the validated culture code or default
//
private string ValidateCulture(string userCulture)
{
if (string.IsNullOrEmpty(userCulture))
{
//no culture found - return default
return SupportedCultures.FirstOrDefault().Key;
}
if (SupportedCultures.Keys.Any(x => x.Equals(userCulture, StringComparison.InvariantCultureIgnoreCase)))
{
//culture is supported by the application!
return userCulture;
}
// find closest match based on the main language. for example
// if the user request en-GB return en-US as it is still an English language
var mainLanguage = GetNeutralCulture(userCulture);
foreach (var lang in SupportedCultures)
{
if (lang.Key.StartsWith(mainLanguage)) return lang.Key;
}
return SupportedCultures.FirstOrDefault().Key;
}
//
// Called from the OnInitialise method. Sets the culture based on the users cookie or accepted language
//
public void CheckGlobalCookie()
{
string cultureCode;
var cookie = _request.Cookies["Globalisation"];
if (cookie != null)
{
cultureCode = cookie.Value;
}
else
{
cultureCode = UserLanguges != null ? UserLanguges[0] : null;
}
//
// Check we support this culture in our application
//
var culture = ValidateCulture(cultureCode);
//
// Set the current threads culture
//
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(culture);
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
}
//
// Summary
// Called when the user picks there own culture
//
public void SetGlobalisationCookie(string culture)
{
culture = ValidateCulture(culture);
var cookie = _request.Cookies["Globalisation"];
if (cookie != null)
{
cookie.Value = culture;
}
else
{
cookie = new HttpCookie("Globalisation")
{
Value = culture,
Expires = DateTime.Now.AddYears(1)
};
}
cookie.Domain = FormsAuthentication.CookieDomain;
_response.Cookies.Add(cookie);
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(culture);
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
}
}
要使用它,只需重写控制器的 Initialize 方法
protected override void Initialize(RequestContext requestContext)
{
new GlobalisationCookie(requestContext.HttpContext.Request, requestContext.HttpContext.Response).CheckGlobalCookie();
base.Initialize(requestContext);
}
这种方法的好处是,系统会在用户第一次进入应用程序时根据他们的浏览器设置自动设置文化,而用户并不知道。
它也可以回退到主要语言,所以如果用户请求 en-US 但应用程序只支持 en-GB,它足够聪明 return en-GB 因为它仍然是英语。
如果您有任何问题,请告诉我:)
我的 mvc 应用程序中有一个基本控制器,所有控制器都继承自该控制器。基本控制器继承 System.Web.Mvc
命名空间中的抽象 class 控制器,我需要在每个控制器操作上设置文化。我可以重写许多方法,例如 OnActionExecuting, Initialize, ExecuteCore, BeginExecute
考虑绩效哪一个最适合这份工作? (以上 4 种方法只是示例,完整列表参见 MSDN)
我们实施了一种根据用户 Accept-Language header 改变文化的方法,但也允许他们自己明确设置,我们问自己同样的问题。
我们发现 Initialize 方法是设置它的最佳位置,因为它在其他方法之前和任何操作过滤器之前被调用。这对我们很重要,因为我们希望动作过滤器能够尊重预期的文化。
我不确定在每种方法中设置文化是否会有任何性能差异。我相信它们只会在不同的时间点执行,即在操作过滤器之前、模型绑定之前和临时数据加载之后等。
我相信我们在源代码库的某个地方有一个助手 class 可以概述我们是如何做到的。让我知道你是否喜欢这个,我会把它挖出来。
抱歉,我知道你的问题更具体,我只是想分享我的经验。
更新
这里要求的是我们用过的助手class
public class GlobalisationCookie
{
public GlobalisationCookie(HttpRequestBase request, HttpResponseBase response)
{
_request = request;
_response = response;
}
private readonly HttpRequestBase _request;
private readonly HttpResponseBase _response;
//
// Gets a collection of users languages from the Accept-Language header in their request
//
private String[] UserLanguges
{
get
{
return _request.UserLanguages;
}
}
//
// A dictionary of cultures the application supports - We point this to a custom webconfig section
// This collection is in order of priority
public readonly Dictionary<string, string> SupportedCultures = new Dictionary<string, string>() { { "en-GB", "English - British" }, { "no", "Norwegian"} }
//
// Summary:
// reads the first part of the culture i.e "en", "es"
//
private string GetNeutralCulture(string name)
{
if (!name.Contains("-")) return name;
return name.Split('-')[0];
}
//
// Summary:
// returns the validated culture code or default
//
private string ValidateCulture(string userCulture)
{
if (string.IsNullOrEmpty(userCulture))
{
//no culture found - return default
return SupportedCultures.FirstOrDefault().Key;
}
if (SupportedCultures.Keys.Any(x => x.Equals(userCulture, StringComparison.InvariantCultureIgnoreCase)))
{
//culture is supported by the application!
return userCulture;
}
// find closest match based on the main language. for example
// if the user request en-GB return en-US as it is still an English language
var mainLanguage = GetNeutralCulture(userCulture);
foreach (var lang in SupportedCultures)
{
if (lang.Key.StartsWith(mainLanguage)) return lang.Key;
}
return SupportedCultures.FirstOrDefault().Key;
}
//
// Called from the OnInitialise method. Sets the culture based on the users cookie or accepted language
//
public void CheckGlobalCookie()
{
string cultureCode;
var cookie = _request.Cookies["Globalisation"];
if (cookie != null)
{
cultureCode = cookie.Value;
}
else
{
cultureCode = UserLanguges != null ? UserLanguges[0] : null;
}
//
// Check we support this culture in our application
//
var culture = ValidateCulture(cultureCode);
//
// Set the current threads culture
//
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(culture);
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
}
//
// Summary
// Called when the user picks there own culture
//
public void SetGlobalisationCookie(string culture)
{
culture = ValidateCulture(culture);
var cookie = _request.Cookies["Globalisation"];
if (cookie != null)
{
cookie.Value = culture;
}
else
{
cookie = new HttpCookie("Globalisation")
{
Value = culture,
Expires = DateTime.Now.AddYears(1)
};
}
cookie.Domain = FormsAuthentication.CookieDomain;
_response.Cookies.Add(cookie);
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(culture);
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
}
}
要使用它,只需重写控制器的 Initialize 方法
protected override void Initialize(RequestContext requestContext)
{
new GlobalisationCookie(requestContext.HttpContext.Request, requestContext.HttpContext.Response).CheckGlobalCookie();
base.Initialize(requestContext);
}
这种方法的好处是,系统会在用户第一次进入应用程序时根据他们的浏览器设置自动设置文化,而用户并不知道。
它也可以回退到主要语言,所以如果用户请求 en-US 但应用程序只支持 en-GB,它足够聪明 return en-GB 因为它仍然是英语。
如果您有任何问题,请告诉我:)