Member 12749751 Ответов: 1

Не удается прочитать объект httpcontext в блоке catch в .NET core


Я должен выполнить глобальную обработку ошибок для этого я создал пользовательскую среднюю посуду
но при обработке ошибок я должен регистрировать весь запрос также поэтому в блоке catch я регистрирую запрос также но в блоке catch параметр тела запроса всегда пуст где как и в блоке try я могу получить объект тела запроса

Что я уже пробовал:

public class HTTPStatuseCodeExceptionMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IErrorLogApplicationService _ErrorLogApplicationService;
        public HTTPStatuseCodeExceptionMiddleware(RequestDelegate next, IErrorLogApplicationService ErrorLogApplicationService)
        {
            _next = next ?? throw new ArgumentNullException(nameof(next));
            _ErrorLogApplicationService = ErrorLogApplicationService;
        }

        public async Task Invoke(HttpContext context)
        {
            try
            {
                string IPAddress = GetIPAddress();
                string Request = FormatRequest(context.Request).Result;
                await _next(context);
            }
            catch (HTTPStatusCodeException ex)
            {
                context.Response.Clear();
                context.Response.StatusCode = ex.StatusCode;
                context.Response.ContentType = ex.ContentType;

                await context.Response.WriteAsync(ex.Message);
               // ErrorLog(context, ex);
                return;
            }
            catch(Exception ex)
            {
                
                string Request = FormatRequest(context.Request).Result;
                // ErrorLog(context, ex);
            }

        }

//Format Request method

private async Task<string> FormatRequest(HttpRequest request)
        {
            var body = request.Body;

            //This line allows us to set the reader for the request back at the beginning of its stream.
            request.EnableRewind();

            //We now need to read the request stream.  First, we create a new byte[] with the same length as the request stream...
            var buffer = new byte[Convert.ToInt32(request.ContentLength)];

            //...Then we copy the entire request stream into the new buffer.
            await request.Body.ReadAsync(buffer, 0, buffer.Length);

            //We convert the byte[] into a string using UTF8 encoding...
            var bodyAsText = Encoding.UTF8.GetString(buffer);

            //..and finally, assign the read body back to the request body, which is allowed because of EnableRewind()
            request.Body = body;

            return $"{request.Scheme} {request.Host}{request.Path} {request.QueryString} {bodyAsText}";
        }

1 Ответов

Рейтинг:
1

Andy Lanng

Не используйте промежуточное программное обеспечение, вместо этого используйте фильтр запросов.

Для обработки исключений следует использовать промежуточное программное обеспечение. Он всегда должен был считать ответ полным. У нас есть аналогичное промежуточное программное обеспечение, которое регистрирует весь трафик в сервисе и из него. У нас есть фильтры, которые обрабатывают исключения и превращают их в изящные ответы после регистрации проблемы.

public class GeneralExceptionFilterAttribute : ExceptionFilterAttribute {

        public override void OnException(HttpActionExecutedContext context) {
            FilterHandlerProvider.Instance.Handle(this, context);
        }

    }

Я не буду вдаваться в подробности о FilterHandlerProvider.Например, потому что мы используем фабрику DI для обработки различных типов исключений. В этом конкретном случае экземпляр устанавливается как наш GeneralExceptionFilterAttribute.

public class GeneralExceptionFilterAttributeHandler : IHandlesFilterAttribute<GeneralExceptionFilterAttribute,
        HttpActionExecutedContext> {

        private readonly ILogger _logger;

        public GeneralExceptionFilterAttributeHandler(ILogger logger) {
            _logger = logger;
        }

        public void Handle(GeneralExceptionFilterAttribute filter, HttpActionExecutedContext context) {

            var extraInformation = new List<object>();
#if DEBUG
            //We want to handle all exceptions when they occur so we break the debugger here to take a look at an unhandled general exception and try to handle it
            Debugger.Break();
#endif
            if (context.Exception is HttpResponseException responseException) {
                context.Response = responseException.Response;
            }
            else if (context.Exception is InvalidAggregateOperationException invalidAggregateOperationException) {
                extraInformation.Add(invalidAggregateOperationException.AggregateId);
                if (invalidAggregateOperationException.InnerException != null) {
                    if (context.Exception.InnerException is ItemsNotAvailableException itemsNotAvailableException) {
                        extraInformation.Add(itemsNotAvailableException.Type);
                    }
                }
            }
            else {
                context.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }

            _logger.LogException(context.Exception, extraInformation.ToArray());
        }

    }


Наш ILogger-это экземпляр DI, поэтому вы можете сделать это по-другому.

Самое главное, что любое исключение, поступающее от контроллера, обрабатывается, регистрируется и устанавливается изящный ответ.

Вот еще кое-что почитать о фильтрах:
Понимание фильтров в MVC[^]

Надеюсь, это поможет ^_^


Member 12749751

Но за исключением этого я должен регистрировать весь запрос с параметрами..тогда как я могу это сделать

Andy Lanng

Правильно, у вас все еще есть доступ к контекстному запросу в фильтре.