3

我目前正在从 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 视图中更改当前的线程 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;
}

这看起来不优雅和笨拙。有什么更好的方法来做到这一点?

*编辑:我正在寻找两个挂钩点:一个在视图被调用之前,一个在它被渲染之后。这些应该保持对其他请求的干扰为零。

4

1 回答 1

3

我今天发现自定义 IServiceRunner 提供了正确的钩子(请参阅https://github.com/ServiceStack/ServiceStack/wiki/Customize-HTTP-Responses)。

如上所述,它仅在页面由 Service 提供服务时才有效,因为在请求 ContentPage 时甚至不会触及 RequestFilters 和 ServiceRunner。

有趣的是,RequestFilter 是另一个挂钩点,它在视图的执行之前被调用。但对于 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);
    }
}
于 2013-11-06T14:21:40.297 回答