我目前从Accept-Language-HTTP-Header获取首选文化,并将其存储在 AuthUserSession 中。
在AppHost.Configure:
PreRequestFilters.Add((httpReq, httpResp) =>
{
var session = httpReq.GetSession();
if (session is AuthUserSession)
{
var auths = ((AuthUserSession)session);
if (auths.Culture == null)
{
//parse languages
var languages = httpReq.Headers["Accept-Language"];
//auths.Culture = Helpers.CultureHelper.GetBestAcceptLanguageMatch(languages);
auths.Culture = "en-US";
httpReq.SaveSession(session, new TimeSpan(0, 20, 0));
}
}
});
我目前在用户首选文化中渲染视图的解决方案是从Razor视图更改当前的Threads UICulture:
@inherits ViewPage<LandingPage.ServiceModel.Operations.AskQuestions>
@{
var session = GetSession<ServiceStack.ServiceInterface.Auth.AuthUserSession>();
var prevCulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(session.Culture);
//access a Resource
ViewBag.Title = Resources.AskTitle;
}
Views Content
@{
System.Threading.Thread.CurrentThread.CurrentUICulture = prevCulture;
}
这似乎不够优雅和笨拙。什么是更好的方法呢?
*编辑: 我正在寻找两个钩点:一个在View被调用之前,一个在它被渲染之后。这些应该保持对其他请求服务为零的干扰。
答案 0 :(得分:3)
我今天发现自定义IServiceRunner只提供正确的挂钩(参见https://github.com/ServiceStack/ServiceStack/wiki/Customize-HTTP-Responses)。
如上所述,当页面由服务提供时,它才起作用,因为请求ContentPage时甚至没有触及RequestFilters和ServiceRunner。
可能有意义的是,RequestFilter是另一个挂钩点,在执行View之前调用。但对于ResponseFilter来说,情况也是如此。我试图在ResponseFilter中重置CurrentUICulture的一个小测试使我的页面未本地化。
在 AppHost
中public override void Configure(Funq.Container container)
{
//plugins
Plugins.Add(new RazorFormat());
Plugins.Add(new AuthFeature(() =>
new AuthUserSession(),
new IAuthProvider[] {
new BasicAuthProvider()
}));
//request filters
PreRequestFilters.Add((httpReq, httpResp) =>
{
var session = httpReq.GetSession();
if (session is AuthUserSession)
{
var auths = ((AuthUserSession)session);
if (auths.Culture == null)
{
var languages = httpReq.Headers["Accept-Language"];
auths.Culture = Helpers.CultureHelper.GetBestAcceptLanguageMatch(languages);
httpReq.SaveSession(session, new TimeSpan(0, 20, 0));
}
httpReq.SetItem("Culture", auths.Culture);
}
});
//funq
var userRep = new InMemoryAuthRepository();
container.Register<IUserAuthRepository>(userRep);
container.Register<ICacheClient>(c => new MemoryCacheClient());
}
//use a custom IServiceRunner
public override ServiceStack.ServiceHost.IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext actionContext)
{
var runner = base.CreateServiceRunner<TRequest>(actionContext);
return new CultureAwareServiceRunner<TRequest>(this, actionContext);
}
<强> CultureAwareServiceRunner.cs 强>
public class CultureAwareServiceRunner<T> : ServiceRunner<T>
{
public CultureAwareServiceRunner(AppHost appHost, ServiceStack.WebHost.Endpoints.ActionContext actionContext) :
base(appHost, actionContext)
{ }
public override void OnBeforeExecute(IRequestContext requestContext, T request)
{
var httpReq = requestContext.Get<IHttpRequest>();
httpReq.SetItem("PreviousCulture", Thread.CurrentThread.CurrentUICulture);
string culture = httpReq.GetItem("Culture") as string;
if (culture != null)
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture);
base.OnBeforeExecute(requestContext, request);
}
public override object OnAfterExecute(IRequestContext requestContext, object response)
{
var httpReq = requestContext.Get<IHttpRequest>();
var prevCulture = httpReq.GetItem("PreviousCultureCulture") as CultureInfo;
if (prevCulture != null)
Thread.CurrentThread.CurrentUICulture = prevCulture;
return base.OnAfterExecute(requestContext, response);
}
}