我需要为发送到使用ServiceStack 3
和编写的 Web 应用程序的每个 Web 请求设置用户特定的文化MVC 4
。
每个用户的文化都存储在他们在数据库中的个人资料中,我将其检索到我自己的IAuthSession
使用从CredentialsAuthProvider
. 所以我不关心浏览器的AcceptLanguage
标题,而是想在ServiceStack
从缓存中解析它之后立即将当前线程的文化设置为身份验证会话的文化属性。这对于ServiceStack
服务和MVC
控制器(源自ServiceStackController
)都必须发生。
完成上述任务的最佳方法是什么?
更新 1
我找到了一种方法来做到这一点,尽管我不相信这是最佳解决方案。
在派生所有服务的基础服务类中,我SessionAs<>
按如下方式覆盖了该属性:
protected override TUserSession SessionAs<TUserSession>()
{
var genericUserSession = base.SessionAs<TUserSession>();
var userAuthSession = genericUserSession as UserAuthSession;
if (userAuthSession != null && !String.IsNullOrWhiteSpace(userAuthSession.LanguageCode))
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(userAuthSession.LanguageCode);
return genericUserSession;
}
UserAuthSession
我的 ServiceStack 的自定义实现在哪里IAuthSession
?它的LanguageCode
属性在登录时设置为存储在数据库中用户配置文件中的用户选择的 ISO 文化代码。
同样,在我的所有控制器派生自的基本控制器类中,我AuthSession
像这样覆盖了该属性:
public override IAuthSession AuthSession
{
get
{
var userAuthSession = base.AuthSession as UserAuthSession;
if (userAuthSession != null && !String.IsNullOrWhiteSpace(userAuthSession.LanguageCode))
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(userAuthSession.LanguageCode);
return userAuthSession;
}
}
这似乎工作正常,因为这两个属性在调用服务或执行控制器操作时始终如一地使用,因此在执行任何下游逻辑之前设置当前线程的文化。
如果有人能想到更好的方法,请告诉我。
更新 2
根据 Scott 的建议,我创建了一个自定义AuthenticateAndSetCultureAttribute
:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class AuthenticateAndSetCultureAttribute : AuthenticateAttribute
{
public AuthenticateAndSetCultureAttribute() : base() { }
public AuthenticateAndSetCultureAttribute(ApplyTo applyTo) : base(applyTo) { }
public AuthenticateAndSetCultureAttribute(string provider) : base(provider) { }
public AuthenticateAndSetCultureAttribute(ApplyTo applyTo, string provider) : base(applyTo, provider) { }
public override void Execute(IHttpRequest req, IHttpResponse res, object requestDto)
{
base.Execute(req, res, requestDto);
var session = req.GetSession() as UserAuthSession;
if (session != null && session.IsAuthenticated && !String.IsNullOrWhiteSpace(session.LanguageCode))
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(session.LanguageCode);
}
}
因为我只在用户通过身份验证时更改文化,所以(无论如何在我看来)在我们检查身份验证的同一个地方执行它是有意义的。
然后我用这个属性而不是原来的[Authenticate]
.
现在,当调用 SS 服务时,将Execute
执行属性的方法,并正确设置文化。但是,Execute
当调用 MVC 控制器操作时,永远不会执行,这真的很令人费解,因为 MVC+SS 怎么知道将未经身份验证的请求重定向到登录页面。
有什么想法,有人吗?