在ASP.NET中,无法为每个请求设置文化

时间:2015-06-30 11:04:58

标签: c# asp.net asp.net-mvc asp.net-mvc-3 localization

为每个请求设置文化设置应该很简单,对吧?好吧,它不是因为你在一个线程而不是一个请求上设置文化设置,显然ASP.NET并不总是在一个线程上执行整个请求。当然我可以使用DefaultThreadCurrentCulture,但这会在所有线程上设置文化,而不仅仅是特定请求使用的文化。

我在这里错过了什么或什么?因为当我在Global.asax的Application_AcquireRequestState()函数中设置文化时(因此它在每个请求的开头执行一次)由于某种原因我有多种语言的属性显示名称,当我深入挖掘时,我发现在显示名称属性的构造函数中,CurrentCulture和CurrentUICulture设置有时与我在Global.asax中设置的完全不同。

我确定问题不在我的自定义显示名称属性中,但您仍然可以在下方看到它:

public class DDisplayName : DisplayNameAttribute
    {
        public DDisplayName(string resourceId)
            : base(GetAttributeName(resourceId))
        {  }

        private static string GetAttributeName(string resourceId)
        {
            var lang = System.Threading.Thread.CurrentThread.CurrentCulture.LCID + "|" + System.Threading.Thread.CurrentThread.CurrentUICulture.LCID;

            ResourceManager resMan = new ResourceManager(typeof(Strings));

            string result = resMan.GetString(resourceId);

            return result == null ? "Resource string: " + resourceId + " not found" : result+" "+lang;

        }
    }

正如你所看到的,我甚至添加了LCIDs的显示名称,以便我可以在屏幕上看到它们,文化设置也不同。

编辑:我还在上面的调试输出中添加了时间戳和线程ID。

var lang = System.Threading.Thread.CurrentThread.CurrentCulture.LCID + "|" + System.Threading.Thread.CurrentThread.CurrentUICulture.LCID;
lang += "(" + System.Threading.Thread.CurrentThread.ManagedThreadId + " | "+DateTime.Now.ToString("HH:mm:ss:fff")+")";

事实证明它在请求之间保留了DDisplayName属性实例......呵呵?基本上,当Html.LabelFor()运行时,它会查看属性的元数据以查找显示名称。当元数据提供者设置元数据时,它从PropertyDescriptor实例中找到显示名称,该实例包含属性的属性列表。在此列表中,属性实例由于某种原因是来自先前请求的旧属性(我知道由于我在构造函数中添加到displayname的时间戳)。因此,在我切换语言之后,它仍然使用我在设置上一语言时所拥有的旧属性实例。那么发生了什么?为什么不在每个请求上创建一个新的DDisplayName对象实例?

编辑2:我不知道为什么它继续兑现属性实例,所以我只编写了自己的MetaDataProvider,它继承自DataAnnotationsModelMetadataProvider,并确保它找到真实的(最新的)显示名称。

0 个答案:

没有答案