C# 如何阅读HttpResponse正文?
我有一个带有请求和响应日志记录中间件的.NET核心Web API项目。我在C# 如何阅读HttpResponse正文?,c#,asp.net-core,.net-core,C#,Asp.net Core,.net Core,我有一个带有请求和响应日志记录中间件的.NET核心Web API项目。我在Startup文件的Configure方法中注册了这两个中间件文件 app.UseMiddleware<RequestLoggingMiddleware>(); app.UseMiddleware<ResponseLoggingMiddleware>(); 但不幸的是我得到了这个例外 System.ArgumentException:流不可读 有人知道如何修复它吗?您可以使用StreamReade
Startup
文件的Configure
方法中注册了这两个中间件文件
app.UseMiddleware<RequestLoggingMiddleware>();
app.UseMiddleware<ResponseLoggingMiddleware>();
但不幸的是我得到了这个例外
System.ArgumentException:流不可读
有人知道如何修复它吗?您可以使用StreamReader读取请求正文。下面的代码,您可以按照
string body = string.Empty;
Request.EnableRewind();
using (var reader = new StreamReader(Request.Body))
{
Request.Body.Seek(0, SeekOrigin.Begin);
body = reader.ReadToEnd();
}
同样的方法,你可以得到一个响应体
using (var reader = new StreamReader(Response.Body))
{
Response.Body.Seek(0, SeekOrigin.Begin);
body = reader.ReadToEnd();
}
根据这里接受的答案 我对解决方案做了一点修改,使它起了作用。我想分享我的解决方案,如何记录每个传入的请求和每个传出的响应 如果您认为此解决方案容易出错或可以改进,请发表评论 对于请求日志记录:
public class RequestLoggingMiddleware
{
private readonly RequestDelegate requestDelegate;
private readonly ILogger<RequestLoggingMiddleware> logger;
public RequestLoggingMiddleware(RequestDelegate requestDelegate, ILogger<RequestLoggingMiddleware> logger)
{
this.requestDelegate = requestDelegate;
this.logger = logger;
}
public async Task InvokeAsync(HttpContext httpContext)
{
await LogRequest(httpContext.Request);
await requestDelegate(httpContext);
}
private async Task LogRequest(HttpRequest httpRequest)
{
StringBuilder stringBuilder = new StringBuilder();
AppendMethod(httpRequest, stringBuilder);
AppendPath(httpRequest, stringBuilder);
AppendContentType(httpRequest, stringBuilder);
AppendHeaders(httpRequest, stringBuilder);
AppendParams(httpRequest, stringBuilder);
AppendQueries(httpRequest, stringBuilder);
await AppendBody(httpRequest, stringBuilder);
logger.LogTrace(stringBuilder.ToString());
}
private void AppendMethod(HttpRequest httpRequest, StringBuilder stringBuilder)
{
stringBuilder.AppendLine($"Method: {httpRequest.Method}");
}
private void AppendPath(HttpRequest httpRequest, StringBuilder stringBuilder)
{
stringBuilder.AppendLine($"Path: {httpRequest.Path.Value}");
}
private void AppendContentType(HttpRequest httpRequest, StringBuilder stringBuilder)
{
string contentType = httpRequest.ContentType;
if (!string.IsNullOrEmpty(contentType))
{
stringBuilder.AppendLine($"Content type: {contentType}");
}
}
private void AppendHeaders(HttpRequest httpRequest, StringBuilder stringBuilder)
{
AppendCollection(httpRequest.Headers, "Headers", stringBuilder);
}
private void AppendParams(HttpRequest httpRequest, StringBuilder stringBuilder)
{
AppendCollection(httpRequest.RouteValues, "Params", stringBuilder);
}
private void AppendQueries(HttpRequest httpRequest, StringBuilder stringBuilder)
{
AppendCollection(httpRequest.Query, "Queries", stringBuilder);
}
private void AppendCollection<TKey, TValue>(
IEnumerable<KeyValuePair<TKey, TValue>> collection,
string collectionName,
StringBuilder stringBuilder)
{
if (collection.Any())
{
stringBuilder.AppendLine($"{collectionName}:");
foreach ((TKey key, TValue value) in collection)
{
stringBuilder.AppendLine($"\t{key}: {value}");
}
}
}
private async Task AppendBody(HttpRequest httpRequest, StringBuilder stringBuilder)
{
httpRequest.EnableBuffering();
ReadResult bodyReadResult = await httpRequest.BodyReader.ReadAsync();
ReadOnlySequence<byte> bodyBuffer = bodyReadResult.Buffer;
if (bodyBuffer.Length > 0)
{
byte[] bodyBytes = bodyBuffer.ToArray();
string bodyText = Encoding.UTF8.GetString(bodyBytes);
stringBuilder.AppendLine($"Body: {bodyText}");
}
httpRequest.Body.Seek(0, SeekOrigin.Begin);
}
}
公共类requestLogging中间件
{
私有只读RequestDelegate RequestDelegate;
专用只读ILogger记录器;
公共RequestLoggingMiddleware(RequestDelegate、RequestDelegate、ILogger记录器)
{
this.requestDelegate=requestDelegate;
this.logger=记录器;
}
公共异步任务InvokeAsync(HttpContext HttpContext)
{
等待LogRequest(httpContext.Request);
等待请求委托(httpContext);
}
专用异步任务日志请求(HttpRequest HttpRequest)
{
StringBuilder StringBuilder=新的StringBuilder();
AppendMethod(httpRequest、stringBuilder);
AppendPath(httpRequest、stringBuilder);
AppendContentType(httpRequest、stringBuilder);
附录标题(httpRequest、stringBuilder);
AppendParams(httpRequest、stringBuilder);
附加查询(httpRequest、stringBuilder);
等待AppendBody(httpRequest、stringBuilder);
logger.LogTrace(stringBuilder.ToString());
}
私有方法(HttpRequest HttpRequest、StringBuilder StringBuilder)
{
AppendLine($“方法:{httpRequest.Method}”);
}
私有无效附加路径(HttpRequest HttpRequest、StringBuilder StringBuilder)
{
stringBuilder.AppendLine($“路径:{httpRequest.Path.Value}”);
}
私有void AppendContentType(HttpRequest HttpRequest、StringBuilder StringBuilder)
{
字符串contentType=httpRequest.contentType;
如果(!string.IsNullOrEmpty(contentType))
{
AppendLine($“内容类型:{contentType}”);
}
}
私有void AppendHeaders(HttpRequest HttpRequest、StringBuilder StringBuilder)
{
AppendCollection(httpRequest.Headers,“Headers”,stringBuilder);
}
私有void AppendParams(HttpRequest HttpRequest、StringBuilder StringBuilder)
{
AppendCollection(httpRequest.RouteValue,“参数”,stringBuilder);
}
私有查询(HttpRequest HttpRequest、StringBuilder StringBuilder)
{
AppendCollection(httpRequest.Query,“查询”,stringBuilder);
}
私人收藏(
IEnumerable collection,
字符串集合名称,
StringBuilder(StringBuilder)
{
if(collection.Any())
{
AppendLine($“{collectionName}:”);
集合中的foreach((TKey键,TValue值)
{
AppendLine($“\t{key}:{value}”);
}
}
}
专用异步任务AppendBody(HttpRequest HttpRequest、StringBuilder StringBuilder)
{
httpRequest.EnableBuffering();
ReadResult bodyReadResult=等待httpRequest.BodyReader.ReadAsync();
ReadOnlySequence bodyBuffer=bodyReadResult.Buffer;
如果(bodyBuffer.Length>0)
{
byte[]bodyBytes=bodyBuffer.ToArray();
字符串bodyText=Encoding.UTF8.GetString(bodyBytes);
AppendLine($“Body:{bodyText}”);
}
httpRequest.Body.Seek(0,SeekOrigin.Begin);
}
}
响应日志记录有点不同
public class ResponseLoggingMiddleware
{
private readonly RequestDelegate requestDelegate;
private readonly ILogger<RequestLoggingMiddleware> logger;
public ResponseLoggingMiddleware(RequestDelegate requestDelegate, ILogger<RequestLoggingMiddleware> logger)
{
this.requestDelegate = requestDelegate;
this.logger = logger;
}
public async Task InvokeAsync(HttpContext httpContext)
{
HttpResponse httpResponse = httpContext.Response;
Stream originalBody = httpResponse.Body;
try
{
using (MemoryStream memoryStream = new MemoryStream())
{
httpResponse.Body = memoryStream;
await requestDelegate(httpContext);
await LogResponse(httpContext.Response, originalBody, memoryStream);
}
}
finally
{
httpContext.Response.Body = originalBody;
}
}
private async Task LogResponse(HttpResponse httpResponse, Stream originalBody, MemoryStream memoryStream)
{
StringBuilder stringBuilder = new StringBuilder();
AppendStatusCode(httpResponse, stringBuilder);
AppendContentType(httpResponse, stringBuilder);
await AppendBody(httpResponse, stringBuilder, originalBody, memoryStream);
logger.LogTrace(stringBuilder.ToString());
}
private void AppendStatusCode(HttpResponse httpResponse, StringBuilder stringBuilder)
{
stringBuilder.AppendLine($"Status code: {httpResponse.StatusCode}");
}
private void AppendContentType(HttpResponse httpResponse, StringBuilder stringBuilder)
{
string contentType = httpResponse.ContentType;
if (!string.IsNullOrEmpty(contentType))
{
stringBuilder.AppendLine($"Content type: {contentType}");
}
}
private async Task AppendBody(HttpResponse httpResponse, StringBuilder stringBuilder, Stream originalBody, MemoryStream memoryStream)
{
httpResponse.Body.Seek(0, SeekOrigin.Begin);
StreamReader streamReader = new StreamReader(memoryStream);
string bodyText = await streamReader.ReadToEndAsync();
if (bodyText.Length > 0)
stringBuilder.AppendLine($"Body: {bodyText}");
httpResponse.Body.Seek(0, SeekOrigin.Begin);
await memoryStream.CopyToAsync(originalBody);
}
}
公共类响应日志中间件
{
私有只读RequestDelegate RequestDelegate;
专用只读ILogger记录器;
公共响应日志中间件(RequestDelegate RequestDelegate、ILogger logger)
{
this.requestDelegate=requestDelegate;
this.logger=记录器;
}
公共异步任务InvokeAsync(HttpContext HttpContext)
{
HttpResponse HttpResponse=httpContext.Response;
Stream originalBody=httpResponse.Body;
尝试
{
使用(MemoryStream MemoryStream=new MemoryStream())
{
httpResponse.Body=内存流;
等待请求委托(httpContext);
等待LogResponse(httpContext.Response、originalBody、memoryStream);
}
}
最后
{
httpContext.Response.Body=原始正文;
}
}
专用异步任务日志响应(HttpResponse HttpResponse、流原始体、MemoryStream MemoryStream)
{
StringBuilder StringBuilder=新的StringBuilder();
AppendStatusCode(httpResponse、stringBuilder);
AppendContentType(httpResponse、stringBuilder);
等待AppendBody(httpResponse、stringBuilder、originalBody、memoryStream);
logger.LogTrace(stringBuilder.ToString());
}
私有状态代码(HttpResponse HttpResponse,StringBuilder StringBuilder)
{
stringBuilder.AppendLine($“状态代码:{httpResponse.StatusCode}”);
}
私有void AppendContentType(HttpResponse HttpResponse,StringBuilder StringBuilder)
{
字符串contentType=httpResponse.contentType;
如果(!string.IsNullOrEmpty(contentType))
{
AppendLine($“内容类型:{contentType}”);
}
}
专用异步任务AppendBody(HttpResponse HttpResponse、StringBuilder StringBuilder、Stream originalBody、MemoryStream MemoryStream)
{
httpResponse
public class RequestLoggingMiddleware
{
private readonly RequestDelegate requestDelegate;
private readonly ILogger<RequestLoggingMiddleware> logger;
public RequestLoggingMiddleware(RequestDelegate requestDelegate, ILogger<RequestLoggingMiddleware> logger)
{
this.requestDelegate = requestDelegate;
this.logger = logger;
}
public async Task InvokeAsync(HttpContext httpContext)
{
await LogRequest(httpContext.Request);
await requestDelegate(httpContext);
}
private async Task LogRequest(HttpRequest httpRequest)
{
StringBuilder stringBuilder = new StringBuilder();
AppendMethod(httpRequest, stringBuilder);
AppendPath(httpRequest, stringBuilder);
AppendContentType(httpRequest, stringBuilder);
AppendHeaders(httpRequest, stringBuilder);
AppendParams(httpRequest, stringBuilder);
AppendQueries(httpRequest, stringBuilder);
await AppendBody(httpRequest, stringBuilder);
logger.LogTrace(stringBuilder.ToString());
}
private void AppendMethod(HttpRequest httpRequest, StringBuilder stringBuilder)
{
stringBuilder.AppendLine($"Method: {httpRequest.Method}");
}
private void AppendPath(HttpRequest httpRequest, StringBuilder stringBuilder)
{
stringBuilder.AppendLine($"Path: {httpRequest.Path.Value}");
}
private void AppendContentType(HttpRequest httpRequest, StringBuilder stringBuilder)
{
string contentType = httpRequest.ContentType;
if (!string.IsNullOrEmpty(contentType))
{
stringBuilder.AppendLine($"Content type: {contentType}");
}
}
private void AppendHeaders(HttpRequest httpRequest, StringBuilder stringBuilder)
{
AppendCollection(httpRequest.Headers, "Headers", stringBuilder);
}
private void AppendParams(HttpRequest httpRequest, StringBuilder stringBuilder)
{
AppendCollection(httpRequest.RouteValues, "Params", stringBuilder);
}
private void AppendQueries(HttpRequest httpRequest, StringBuilder stringBuilder)
{
AppendCollection(httpRequest.Query, "Queries", stringBuilder);
}
private void AppendCollection<TKey, TValue>(
IEnumerable<KeyValuePair<TKey, TValue>> collection,
string collectionName,
StringBuilder stringBuilder)
{
if (collection.Any())
{
stringBuilder.AppendLine($"{collectionName}:");
foreach ((TKey key, TValue value) in collection)
{
stringBuilder.AppendLine($"\t{key}: {value}");
}
}
}
private async Task AppendBody(HttpRequest httpRequest, StringBuilder stringBuilder)
{
httpRequest.EnableBuffering();
ReadResult bodyReadResult = await httpRequest.BodyReader.ReadAsync();
ReadOnlySequence<byte> bodyBuffer = bodyReadResult.Buffer;
if (bodyBuffer.Length > 0)
{
byte[] bodyBytes = bodyBuffer.ToArray();
string bodyText = Encoding.UTF8.GetString(bodyBytes);
stringBuilder.AppendLine($"Body: {bodyText}");
}
httpRequest.Body.Seek(0, SeekOrigin.Begin);
}
}
public class ResponseLoggingMiddleware
{
private readonly RequestDelegate requestDelegate;
private readonly ILogger<RequestLoggingMiddleware> logger;
public ResponseLoggingMiddleware(RequestDelegate requestDelegate, ILogger<RequestLoggingMiddleware> logger)
{
this.requestDelegate = requestDelegate;
this.logger = logger;
}
public async Task InvokeAsync(HttpContext httpContext)
{
HttpResponse httpResponse = httpContext.Response;
Stream originalBody = httpResponse.Body;
try
{
using (MemoryStream memoryStream = new MemoryStream())
{
httpResponse.Body = memoryStream;
await requestDelegate(httpContext);
await LogResponse(httpContext.Response, originalBody, memoryStream);
}
}
finally
{
httpContext.Response.Body = originalBody;
}
}
private async Task LogResponse(HttpResponse httpResponse, Stream originalBody, MemoryStream memoryStream)
{
StringBuilder stringBuilder = new StringBuilder();
AppendStatusCode(httpResponse, stringBuilder);
AppendContentType(httpResponse, stringBuilder);
await AppendBody(httpResponse, stringBuilder, originalBody, memoryStream);
logger.LogTrace(stringBuilder.ToString());
}
private void AppendStatusCode(HttpResponse httpResponse, StringBuilder stringBuilder)
{
stringBuilder.AppendLine($"Status code: {httpResponse.StatusCode}");
}
private void AppendContentType(HttpResponse httpResponse, StringBuilder stringBuilder)
{
string contentType = httpResponse.ContentType;
if (!string.IsNullOrEmpty(contentType))
{
stringBuilder.AppendLine($"Content type: {contentType}");
}
}
private async Task AppendBody(HttpResponse httpResponse, StringBuilder stringBuilder, Stream originalBody, MemoryStream memoryStream)
{
httpResponse.Body.Seek(0, SeekOrigin.Begin);
StreamReader streamReader = new StreamReader(memoryStream);
string bodyText = await streamReader.ReadToEndAsync();
if (bodyText.Length > 0)
stringBuilder.AppendLine($"Body: {bodyText}");
httpResponse.Body.Seek(0, SeekOrigin.Begin);
await memoryStream.CopyToAsync(originalBody);
}
}