Мне нужно установить культуру, специфичную для пользователя, для каждого веб-запроса, отправляемого в мое веб-приложение, написанное с использованием ServiceStack 3
и MVC 4
.
Культура каждого пользователя хранится в его профиле в базе данных, которую я извлекаю в свою собственную реализацию IAuthSession
с помощью пользовательского поставщика аутентификации, полученного из CredentialsAuthProvider
. Поэтому я не забочусь о заголовке браузера AcceptLanguage
и вместо этого хочу установить культуру текущего потока в свойство Culture сеанса аутентификации сразу после того, как 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
По предложению Скотта я создал собственный 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);
}
}
Поскольку я меняю культуру только тогда, когда пользователь аутентифицирован, имеет смысл (во всяком случае, на мой взгляд) сделать это в том же месте, где мы проверяем аутентификацию.
Затем я украсил все свои службы SS и контроллеры MVC этим атрибутом вместо оригинального [Authenticate]
.
Теперь, когда вызывается служба SS, выполняется метод атрибута Execute
, и культура устанавливается правильно. Однако Execute
никогда не выполняется, когда вызывается действие контроллера MVC, что действительно озадачивает, потому что как тогда MVC+SS знает, что нужно перенаправлять неаутентифицированные запросы на страницу входа.
Есть мысли, кто-нибудь?