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

时间:2016-02-22 14:31:20

标签: c# servicestack nlog

我尝试为ServiceStack api中的所有传入请求分配全局请求/跟踪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

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

Windows 10 Update 1上的ServiceStack版本为4.0.52和.net版本4. Nlog版本4.

1 个答案:

答案 0 :(得分:2)

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;
});