title: .Net core middleware httpContext concurrent read and write not supported
body: <p>I have added a middleware in .Net core which log each api request and response to nLog. It works fine for me, even did not noticed any issue with it.
  Today i was trying to make bulk request to API and I received an exception </p>
  
  <blockquote>
    <p>Concurrent reads or writes are not supported
    at <code>await HttpContext.Request.Body.ReadAsync(buffer,0,buffer.Length)</code> where buffer is <code>var buffer= new byte[Convert.ToInt32(HttpContext.Request.ContentLength)]</code></p>
  </blockquote>
  
  <p>I have some confusion at this level</p>
  
  <ol>
  <li>Does .Net core creates separate pipeline for each request. I think yes, as HttpContext.Items are unique to each request cycle.</li>
  <li>If yes, then why I am receiving concurrent error. As my code, first log the request, then pass context to next middleware and lastly log the response. (Does I am missing something?)</li>
  </ol>
  
  <p>Please if you can share the better way to overcome this issue.</p>
  
  <p>Here is code for reference</p>
  
  <pre><code> public class LoggingMiddleware
  {
      readonly ILogger logger;
      readonly RequestDelegate next;
      public LoggingMiddleware(RequestDelegate next, ILogger&lt;LoggingMiddleware&gt; 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");
      }
  
  }
  </code></pre>