在 SS 上下文之外访问 ServiceStack 请求

Accessing ServiceStack request outside of SS context

我正在尝试为 ServiceStack api 中的所有传入请求分配一个全局 request/tracing ID。我通过添加以下预请求过滤器解决了这个问题:

PreRequestFilters.Add((request, response) =>
{
    var requestId = Guid.NewGuid();
    request.Items["RequestId"] = requestId;
});

一切正常 - 我可以在我的自定义 ServiceStack 服务运行程序和所有内容中看到请求 ID。

当我希望将此请求 ID 写入我的日志时出现问题。我正在使用 Nlog,并创建了以下自定义布局渲染器:

public class RequestIdLayoutRenderer : LayoutRenderer
{
    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
        if (ServiceStackHost.Instance == null) return;
        var request = ServiceStackHost.Instance.TryGetCurrentRequest();
        if (request == null) return;

        object requestId;
        if (!request.Items.TryGetValue("RequestId", out requestId)) return;

        builder.Append(requestId);
    }
}

问题是:当返回 request 时,Items 集合仅包含默认的 ServiceStack 元素 AspSessionIDManagerInitializeRequestCalled

我的问题是:这是预期的行为吗?如果是,那么我该如何检索 ServiceStack 范围的 Items 集合 "outside"? 有没有更好的方法来共享此请求 ID,以便 NLog 可以获取它? 我已经在 Nlog 中尝试过 MappedDiagnosticsContext,但由于奇怪的原因,一些日志条目缺少 RequestId,因此这是一种避免使用上下文的尝试。

Windows10 更新 1.Nlog 版本 4.

ServiceStack 版本为 4.0.52 和 .net 版本 4.6

ServiceStack ASP.NET IRequest 保留了字典项的本地副本,该副本最初来源于但与基础 ASP.NET 请求分离。如果你想在 ServiceStack 请求的上下文之外共享数据,但在同一个 ASP.NET 请求中,你可以使用 HttpContext.Current 单例,例如:

PreRequestFilters.Add((request, response) =>
{
    var requestId = Guid.NewGuid();
    HttpContext.Current.Items["RequestId"] = requestId;

    //Alternative API:
    //var aspReq = (HttpRequestBase)request.OriginalRequest;
    //aspReq.Items["RequestId"] = requestId;
});