c# - 如何在 ASP.NET Core 1.0 中记录 HTTP 响应主体

标签 c# asp.net-core-1.0

我正在使用 ASP.NET Core 1.0 RC2 创建一个公共(public) REST Api,并且喜欢记录传入请求和传出响应。

我创建了一个中间件类,它在调用 app.UseMvc() 之前添加到管道中;

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{            
        app.UseIOMiddleware();
        app.UseMvc();            
}

我的中间件类如下所示:

public class IOMiddleware
{
    private readonly RequestDelegate _next;

    public IOMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        LogRequest(context.Request);

        await _next.Invoke(context);            
    }

    private async void LogRequest(HttpRequest request)
    {
        using (var bodyReader = new StreamReader(request.Body))
        {
            string body = await bodyReader.ReadToEndAsync();

            request.Body = new MemoryStream(Encoding.UTF8.GetBytes(body));

            System.Diagnostics.Debug.Print(body);
        }
    }
}

我可以读取请求主体流并使用此示例倒回它:Rewind request body stream ,但我不确定如何读取响应主体,因为流不可读。

在 Web API 2.0 中我可以使用 HttpResponseMessage.Content.ReadAsByteArrayAsync() 方法,但我如何在 ASP.Net Core 1.0 RC2 中完成同样的事情?

最佳答案

问题是 request.Body 不可读,只能写 - 通常流会定期通过线路刷新到客户端。

您可以通过替换流和缓冲内容直到管道的其余部分完成来解决这个问题。

public class IOMiddleware
{
    private readonly RequestDelegate _next;

    public IOMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        await LogRequest(context.Request);

        await LogResponseAndInvokeNext(context);
    }

    private async Task LogRequest(HttpRequest request)
    {
        using (var bodyReader = new StreamReader(request.Body))
        {
            string body = await bodyReader.ReadToEndAsync();

            request.Body = new MemoryStream(Encoding.UTF8.GetBytes(body));
            System.Diagnostics.Debug.Print(body);
        }
    }

    private async Task LogResponseAndInvokeNext(HttpContext context)
    {
        using (var buffer = new MemoryStream())
        {
            //replace the context response with our buffer
            var stream = context.Response.Body;
            context.Response.Body = buffer;

            //invoke the rest of the pipeline
            await _next.Invoke(context);

            //reset the buffer and read out the contents
            buffer.Seek(0, SeekOrigin.Begin);
            var reader = new StreamReader(buffer);
            using (var bufferReader = new StreamReader(buffer))
            {
                string body = await bufferReader.ReadToEndAsync();

                //reset to start of stream
                buffer.Seek(0, SeekOrigin.Begin);

                //copy our content to the original stream and put it back
                await buffer.CopyToAsync(stream);
                context.Response.Body = stream;

                System.Diagnostics.Debug.Print($"Response: {body}");

            }
        }
    }
}

关于c# - 如何在 ASP.NET Core 1.0 中记录 HTTP 响应主体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37855384/

相关文章:

c# - 如何在 mvc 5 中存档而不是删除项目

c# - .NET:ListView 蓝调?

asp.net-core - Asp.Net core 从 url 获取 RouteData 值

c# - ASP.NET CORE 1.0,来自另一个程序集的 AppSettings

c# - 如何使用 mvc 4 向我的 api 添加 token ?

c# - HDF5 .Net 包装器

c# - 请求一个 linq 来操作数组的数组

asp.net - 持久化用户 cookie

asp.net - ASP.net Core中正确的标记用法是什么? TagHelpers与HTML Helper

c# - 如何在 .NET Core 的主布局 View 中呈现特定 Controller 的 Action ?