ServiceStack MQ:如何在 RequestContext 中填充数据

ServiceStack MQ: how to populate data in RequestContext

我正在使用 ServiceStack 开发基于 JWT 的多租户系统。 JWT 令牌包含分片信息,我使用 JwtAuthProvider 按照 http://docs.servicestack.net/jwt-authprovider.

中的说明将 JWT 令牌转换为会话对象

现在想用ServiceStack MQ做异步处理。 MQ 请求需要知道分片信息,所以我在执行之前填充请求上下文,如下所示

mqServer.RegisterHandler<EmployeeAssignedToProject>(m =>
            {
                var req = new BasicRequest { Verb = HttpMethods.Post };
                var sessionKey = SessionFeature.GetSessionKey(m.GetBody().SessionId);
                var session = HostContext.TryResolve<ICacheClient>().Get<Context>(sessionKey);
                req.Items[Keywords.Session] = session;
                var response = ExecuteMessage(m, req);
                return response;
            });

这里,Context是我的自定义会话class。此技术源于 http://docs.servicestack.net/messaging#authenticated-requests-via-mq 处的说明。由于我在 req 的上下文中执行消息,我认为我应该能够解析 Context 如下

container.AddScoped<Context>(c =>
        {
            var webRequest = HostContext.TryGetCurrentRequest();
            if (webRequest != null)
            {
                return webRequest.SessionAs<Context>();
            } else
            {
                return HostContext.RequestContext.Items[Keywords.Session] as Context;                    
            }
        });

但是,HostContext.RequestContext.Items 始终为空。所以问题是,如何从消息处理程序注册代码中填充 HostContext.RequestContext.Items

我尝试深入研究 ServiceStack 代码,发现 ServiceController 中的 ExecuteMessage(IMessage dto, IRequest req) 似乎没有填充 RequestContext 中的数据。就我而言,在服务实例中获取会话有点太晚了,因为服务实例依赖于一些分片信息保存在会话中的数据库连接。

无法从 IOC 解析相同的请求上下文实例。 Request Context 实例是在 MQ 的 RegisterHandler<T>() 中创建的,您可以在 IRequest.Items 属性 中添加自定义数据,例如:

mqServer.RegisterHandler<EmployeeAssignedToProject>(m =>
{
    var req = new BasicRequest { Verb = HttpMethods.Post };
    req.Items[MyKey] = MyValue; //Inject custom per-request data
    //...
    var response = ExecuteMessage(m, req);
    return response;
});

IRequest 实例在整个请求管道和您的服务中的 base.Request 中可用。它在您的 IOC 注册中不可用,因此您需要在调用依赖项时将其作为参数传递,例如:

public class MyServices : Service
{
    public IDependency MyDep { get; set; }

    public object Any(MyRequest request) => MyDep.Method(base.Request, request.Id);
}