1

我需要爲使用ServiceStack 3MVC 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如何知道將未經身份驗證的請求重定向到登錄頁面。

任何想法,任何人?

回答

3

我會這樣做,使用RequestFilter而不是覆蓋SessionAs<T>。在您的AppHostConfigure方法:

public override void Configure(Container container) 
{ 
    RequestFilters.Add((httpReq, httpResp, requestDto) => { 
     var session = httpReq.GetSession() as UserAuthSession; 
     if(session == null || !session.IsAuthenticated || String.IsNullOrWhiteSpace(session.LanguageCode)) 
      return; 

     System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(session.LanguageCode); 
    }); 
} 
+0

感謝您的建議!我更進了一步,並創建了一個自定義驗證屬性(請參閱上面的第二個更新)。它適用於SS服務,但MVC控制器仍存在問題。 –

1

我結束了創建一個自定義的MVC行爲過濾器,其基於經過驗證的用戶的設置請求線程的文化:

public class SetUserCultureAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     base.OnActionExecuting(filterContext); 

     var baseController = filterContext.Controller as BaseController; 
     if (baseController == null) return; 

     var userAuthSession = baseController.UserAuthSession; 
     if (userAuthSession != null && userAuthSession.IsAuthenticated && !String.IsNullOrWhiteSpace(userAuthSession.LanguageCode)) 
      System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(userAuthSession.LanguageCode); 
    } 
} 

然後,我飾我BaseController類與此屬性,並用ServiceStack的常規Authorize屬性保護我的控制器/操作。

以前創建的AuthenticateAndSetCultureAttribute,我原本打算爲控制器和服務現在工作,現在只用於SS服務。

文化在MVC和SS端都能正確設置,所以我很高興!

相關問題