对于多语言ASP.NET MVC 3 Web应用程序,我在控制器工厂确定Thread.CurrentThread.CurrentCulture
和Thread.CurrentThread.CurrentUICulture
如下:
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);
}
}
上面的代码已经快一年了!所以,我愿意接受建议。
我在Global.asax文件上注册这个,如:
ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
这样做很好,但我不确定这是否是做这种行为的最佳做法和最佳场所。
我没有挖到ControllerFactory
的主要角色,我无法将它与ActionFilterAttribute
进行比较。
你怎么看待这种行动的最佳地点?
我使用全球ActionFilter
,但最近我意识到,在某些情况下,用OnActionExecuting
方法设置当前文化为时已晚。例如,当POST请求后的模型进入控制器时,ASP.NET MVC会为模型创建元数据。它发生在执行任何操作之前。因此,DisplayName
属性值,此时使用默认文化处理其他Data Annotations内容。
最终我将当前的文化设置为自定义的IControllerActivator
实现,它就像一个魅力。我认为从请求生命周期的角度来看,在自定义控制器工厂中托管这个逻辑几乎是一样的,就像你今天一样。它比使用全球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()));
}
}
我知道anser已被选中。我们使用的选项是在Application的OnBeginRequest事件中初始化线程当前文化。这确保了每次请求都能发现文化
public void OnBeginRequest(object sender, EventArgs e)
{
var culture = YourMethodForDiscoveringCulutreUsingCookie();
System.Threading.Thread.CurrentThread.CurrentCulture = culture;
System.Threading.Thread.CurrentThread.CurrentUICulture = culture;
}
另一个放置它的地方是将该代码放在自定义ActionFilter的OnActionExecuting方法中,该方法可以在GlobalFilters集合中注册:
http://weblogs.asp.net/gunnarpeipman/archive/2010/08/15/asp-net-mvc-3-global-action-filters.aspx
而不是覆盖OnActionExecuting
你可以像这样覆盖Initialize
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);
}
如果不使用ControllerActivator,可以使用BaseController类和inhеrid。
public class BaseController : Controller
{
public BaseController()
{
//Set CurrentCulture and CurrentUICulture of the thread
}
}
public class HomeController: BaseController
{
[HttpGet]
public ActionResult Index()
{
//..............................................
}
}