Я пытаюсь создать 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
Любой способ решить это?