【发布时间】:2016-07-08 19:51:39
【问题描述】:
我有一个 ASP.NET MVC 5 WEB 应用程序在 IIS 8 的网站下运行,我需要在运行时通过从数据库读取并存储在会话变量中的用户首选项以编程方式更改语言,并且此值可以在运行时使用下拉菜单进行更改。
问题是语言资源有时不会改变,尽管 CurrentCulture 确实如此,更糟糕的是它们在应用程序级别冻结,使得所有其他用户会话也冻结到该语言,并且只会显示在所有应用程序会话使用相同的语言,无论他们的偏好,或者他们甚至尝试在运行时更改他们的语言,这在正常工作时会强制 CurrentThread.CurrentCulture 进行更改。
我在视图中使用了一个隐藏文本来跟踪 CurrentThread.CurrentCulture 是什么以及正在按预期变化所以问题一定出在其他地方。
这是我用来检查 CurrentCulture 的剃刀块
<div style="display:none; visibility: hidden;">Thread
@System.Threading.Thread.CurrentThread.CurrentCulture</div>
在运行时,当语言或 resx 被冻结/卡在应用程序级别时,该值确实是正确的并被选中,但它与视图中显示的语言不匹配,并且在我制作例如 a 之前它不会正常工作更改 web.config 或重新启动应用程序,然后它可以正常工作一段时间,但不要持续太长时间。
<div style="display:none; visibility: hidden;">Thread en-US</div>
问题在于,这发生在所有用户会话的应用程序级别,当应用程序正常工作以及重新启动时,CurrentCulture 实际上会按预期发生变化,但这种情况不会发生,但不知何故,每次用户会话期间都会触发某些事情冻结所有当前会话甚至新会话的语言。
我也尝试将文化逻辑的更改放在剃须刀视图、动作过滤器和基本控制器中,但这并没有解决问题,以前我有一个基本控制器,我的所有控制器都继承了 Global.asax 的逻辑。 cs 来改变和确定文化。
我目前的方法是删除基本控制器并在 Global.asax.cs Application_AcquireRequestState(我也尝试过使用 Application_BeginRequest 但不知何故在生命周期中太早)和操作过滤器中使用。
这是在 Global.asax.cs 中
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
if (Context.Session != null && Context.Session["CultureName"] != null)
{
string cultureName = Context.Session["CultureName"].ToString();
CultureInfo cultureInfo = new System.Globalization.CultureInfo(cultureName);
Thread.CurrentThread.CurrentCulture = cultureInfo;
Thread.CurrentThread.CurrentUICulture = cultureInfo;
}
}
我的动作过滤器是这样的
public class CultureActionAttribute : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
string cultureName = null;
string tenant = filterContext.RouteData.Values["Tenant"] as string;
if (!String.IsNullOrWhiteSpace(tenant))
{
TenantService tenantService = new TenantService(tenant);
cultureName = CultureHelper.GetImplementedCulture(tenantService.Tenant.LanguageCulture);
tenantService.Unit.Dispose();
}
//Logic to override cultureName value by getting the user preference language
CultureInfo cultureInfo = new System.Globalization.CultureInfo(cultureName);
Thread.CurrentThread.CurrentCulture = cultureInfo;
Thread.CurrentThread.CurrentUICulture = cultureInfo;
}
}
我在 FilterConfig 中添加了它
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new CultureActionAttribute());
//
}
我什至尝试在用户更改文化时使用 ClearCachedData。
Thread.CurrentThread.CurrentCulture.ClearCachedData();
我认为这可能与缓存或池回收有关,但我不知道下一步该尝试什么。
我没有在 web.config 中使用任何全球化标签。
在 CurrentThread.CurrentCulture 的视图中跟踪的值始终是正确的,错误的是资源使用冻结。
资源与将它们放在单独的专用标准文件夹中并使用 PublicResXFileCodeGenerator 将它们公开以能够编译并可供控制器、视图等访问的做法是一致的
资源文件夹
谁能给我另一种选择来尝试或思考我可能做错了什么,或者我还可以尝试什么来使资源始终如一地工作。
【问题讨论】:
标签: asp.net asp.net-mvc razor localization currentculture