C# .Net核心中间件httpContext不支持并发读写
我在.NETCore中添加了一个中间件,它记录每个api请求和对nLog的响应。它对我来说很好,甚至没有发现任何问题。 今天我试图向API发出批量请求,但收到了一个异常 不支持并发读取或写入 在C# .Net核心中间件httpContext不支持并发读写,c#,.net-core,asp.net-core-middleware,C#,.net Core,Asp.net Core Middleware,我在.NETCore中添加了一个中间件,它记录每个api请求和对nLog的响应。它对我来说很好,甚至没有发现任何问题。 今天我试图向API发出批量请求,但收到了一个异常 不支持并发读取或写入 在等待HttpContext.Request.Body.ReadAsync(buffer,0,buffer.Length)其中buffer为var buffer=new byte[Convert.ToInt32(HttpContext.Request.ContentLength)] 我在这个层面上有些困惑
等待HttpContext.Request.Body.ReadAsync(buffer,0,buffer.Length)
其中buffer为var buffer=new byte[Convert.ToInt32(HttpContext.Request.ContentLength)]
我在这个层面上有些困惑
public class LoggingMiddleware
{
readonly ILogger logger;
readonly RequestDelegate next;
public LoggingMiddleware(RequestDelegate next, ILogger<LoggingMiddleware> logger)
{
this.logger = logger;
this.next = next;
}
public async Task Invoke(HttpContext context)
{
LogRequest(context);
var originalBodyStream = context.Response.Body;
using (var responseBody = new MemoryStream())
{
context.Response.Body = responseBody;
await next(context).ConfigureAwait(false);
LogResponse(context);
await responseBody.CopyToAsync(originalBodyStream).ConfigureAwait(false);
}
}
private async void LogRequest(HttpContext context)
{
var request = context.Request;
request.EnableRewind();
var buffer = new byte[Convert.ToInt32(request.ContentLength)];
await request.Body.ReadAsync(buffer, 0, buffer.Length);
string requestBody = Encoding.UTF8.GetString(buffer);
request.Body.Seek(0, SeekOrigin.Begin);
context.Items["Request"] = requestBody; //Request is being used in Nlog config
logger.LogInformation("Request received ......"); // Some information
context.Items.Remove("Request");
}
private async void LogResponse(HttpContext context)
{
var response = context.Response;
response.Body.Seek(0, SeekOrigin.Begin);
var responseText = await new StreamReader(response.Body).ReadToEndAsync().ConfigureAwait(false);
response.Body.Seek(0, SeekOrigin.Begin);
context.Items["Response"] = responseText;
logger.LogInformation("Returned response for url with status"); // Information
context.Items.Remove("Response");
}
}
公共类日志中间件
{
只读ILogger记录器;
只读请求委托下一步;
公共日志中间件(RequestDelegate next,ILogger logger)
{
this.logger=记录器;
this.next=next;
}
公共异步任务调用(HttpContext上下文)
{
日志请求(上下文);
var originalBodyStream=context.Response.Body;
使用(var responseBody=newmemorystream())
{
context.Response.Body=responseBody;
等待下一步(上下文)。配置等待(false);
日志响应(上下文);
wait responseBy.CopyToAsync(原始BodyStream).ConfigureWait(false);
}
}
专用异步void日志请求(HttpContext上下文)
{
var-request=context.request;
request.EnableRewind();
var buffer=新字节[Convert.ToInt32(request.ContentLength)];
wait request.Body.ReadAsync(buffer,0,buffer.Length);
string requestBody=Encoding.UTF8.GetString(缓冲区);
request.Body.Seek(0,SeekOrigin.Begin);
context.Items[“Request”]=requestBody;//请求正在Nlog配置中使用
logger.LogInformation(“收到请求……”;//一些信息
上下文。项目。删除(“请求”);
}
专用异步void日志响应(HttpContext上下文)
{
var-response=context.response;
response.Body.Seek(0,SeekOrigin.Begin);
var responseText=await new StreamReader(response.Body).ReadToEndAsync().ConfigureAwait(false);
response.Body.Seek(0,SeekOrigin.Begin);
context.Items[“Response”]=responseText;
logger.LogInformation(“返回的url响应状态”);//信息
上下文。项目。删除(“响应”);
}
}
ASP.NET总是为不同的请求使用不同的线程。HttpContext引用一个特定的请求。这在.NETCore中没有改变。至于错误-代码在哪里?既然代码已经在自己的线程上运行,为什么还要尝试使用另一个线程来访问上下文?您是否使用了ConfigureAwait(false)
也许?当你的方法很可能已经可以访问请求正文时,为什么要使用Request.Body
?请在问题本身中张贴你的代码。不要发布无关文章的链接-这两篇文章是关于日志记录的,而不是关于对HttpContext的跨线程访问您是否可以使用\u next(上下文)代码>而不是等待下一步(上下文)代码>在中间件中?@PanagiotisKanavos Aha!我明白你的意思。是的,我使用的是异步方法,它可能会产生问题。我已经在使用ConfigureAwait(false),但尚未解决。我将再次尝试同步方法,希望我能解决这个问题。正如我所解释的,对于request.Body,它是一个中间件,此时我只能从httpContext读取请求体。感谢您的回复configurewait(false)
很可能是问题的原因。不要尝试同步方法。张贴代码。不要假设ASP.NET核心是断线的。ASP.NET总是为不同的请求使用不同的线程。HttpContext引用一个特定的请求。这在.NETCore中没有改变。至于错误-代码在哪里?既然代码已经在自己的线程上运行,为什么还要尝试使用另一个线程来访问上下文?您是否使用了ConfigureAwait(false)
也许?当你的方法很可能已经可以访问请求正文时,为什么要使用Request.Body
?请在问题本身中张贴你的代码。不要发布无关文章的链接-这两篇文章是关于日志记录的,而不是关于对HttpContext的跨线程访问您是否可以使用\u next(上下文)代码>而不是等待下一步(上下文)代码>在中间件中?@PanagiotisKanavos Aha!我明白你的意思。是的,我使用的是异步方法,它可能会产生问题。我已经在使用ConfigureAwait(false),但尚未解决。我将再次尝试同步方法,希望我能解决这个问题。正如我所解释的,对于request.Body,它是一个中间件,此时我只能从httpContext读取请求体。感谢您的回复configurewait(false)
很可能是问题的原因。不要尝试同步方法。张贴代码。不要假设ASP.NET核心已损坏