我需要爲使用ServiceStack 3
和MVC 4
編寫的發送到我的Web應用程序的每個Web請求設置用戶特定的文化。在ServiceStack + MVC Web應用程序中設置用戶特定的文化
每個用戶的文化都存儲在數據庫的配置文件中,我使用從CredentialsAuthProvider
導出的自定義auth提供程序將其檢索到我自己的實現IAuthSession
。所以我不關心瀏覽器的AcceptLanguage
標題,而是想在ServiceStack
從緩存中解析它之後立刻將當前線程的文化設置爲auth會話的Culture屬性。這對於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
根據斯科特的建議,我創建了一個定製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服務和MVC控制器。
現在當一個SS服務被調用時,屬性的Execute
方法被執行,文化得到正確設置。然而,當調用MVC控制器動作時,Execute
永遠不會執行,這真是令人費解,因爲MVC + SS如何知道將未經身份驗證的請求重定向到登錄頁面。
任何想法,任何人?
感謝您的建議!我更進了一步,並創建了一個自定義驗證屬性(請參閱上面的第二個更新)。它適用於SS服務,但MVC控制器仍存在問題。 –