OwinMiddleware: System.ObjectDisposedException: невозможно получить доступ к удаленному объекту - PullRequest
0 голосов
/ 27 февраля 2019

Я пытаюсь создать OwinMiddleware, который перехватывает все пользовательские запросы и записывает его в БД.Он работает почти нормально, но при высокой загрузке падает с System.ObjectDisposedException: Cannot access a disposed object.

public override async Task Invoke(IOwinContext context)
{
   try
   {
      if (GetMonitoringMode() == (int)MonitoringMode.TurnedOff)
      {
         await Next.Invoke(context);
         return;
      }

      var userId = GetUserId(context);
      if (userId is null || userId == 0)
      {
         await Next.Invoke(context);
         return;
      }

      var startTime = DateTime.UtcNow;

      var flatHeaders = context.Request.Headers?.ToDictionary();
      var trimmedFlatHeaders = flatHeaders?.TrimSecretStrings(KnownHeaderNames.Authorization, SecretStringTrimLimit) ?? "null";

      var requestBody = await GetRequestBody(context, false);
      var trimmedRequestBody = requestBody?.TrimSecretStrings(SecretStringTrimLimit) ?? "null";

      var stream = context.Response.Body;
      var buffer = new MemoryStream();
      context.Response.Body = buffer;

      await Next.Invoke(context);

      buffer.Seek(0, SeekOrigin.Begin);
      var reader = new StreamReader(buffer);
      var responseBody = await reader.ReadToEndAsync();
      var trimmedResponseBody = responseBody?.TrimSecretStrings(SecretStringTrimLimit);

      buffer.Seek(0, SeekOrigin.Begin);
      await buffer.CopyToAsync(stream);

      if (GetMonitoringMode() == (int)MonitoringMode.Partial)  // Here it falls
      {
         trimmedRequestBody = "null";
         trimmedResponseBody = null;
      }

      var endTime = DateTime.UtcNow;
      // Create api call record
      CreateApiCallRecord(new ApiCallRecord
      {
         ApiName = GetApiName(context),
         Ip4Source = context.Request.RemoteIpAddress,
         UserId = userId.Value,
         StartTime = startTime,
         EndTime = endTime,
         Request = "{" +
                     $"\"Request\": {trimmedRequestBody}, " +
                     $"\"Headers\": {trimmedFlatHeaders}" +
                     "}",
         Response = trimmedResponseBody
      });
   }
   catch (Exception ex)
   {
      _logger.LogError($"{ex}");
      return;
   }
}

GetMonitoringMode делает вызов WCF.Я нашел информацию, что закрытие клиента WCF может вызвать проблему.Также вызов этого в начале промежуточного программного обеспечения не падает, поэтому я попытался сохранить его результат в переменной, но он все равно падает с той же ошибкой.

Вот некоторые журналы:

Object name: 'Microsoft.Owin.Host.HttpListener.RequestProcessing.OwinHttpListenerResponse'.
   at Microsoft.Owin.Host.HttpListener.RequestProcessing.OwinHttpListenerResponse.ResponseBodyStarted()
   at Microsoft.Owin.Host.HttpListener.RequestProcessing.ExceptionFilterStream.OneTimeCallback.TryInvoke()
   at Microsoft.Owin.Host.HttpListener.RequestProcessing.ExceptionFilterStream.<WriteAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at ProjectName.UserActivityMonitoringMiddleware.<Invoke>d__2.MoveNext() in ...\UserActivityMonitoringMiddleware.cs:line 62

Любой способ решить это?

...