ASP.NET Core 2.2 не может вызвать Razor Page из пользовательского промежуточного программного обеспечения - PullRequest
0 голосов
/ 23 октября 2019

Я пытаюсь создать специальную промежуточную программу обработки исключений. аналогично -> app.UseExceptionHandler ("/ Ошибка"). Я буду регистрировать ошибку в промежуточном программном обеспечении, а затем я хочу вызвать страницу ошибки. Проблема в том, что когда я делаю перенаправление, то объект IExceptionHandlerFeature из context.Features.Get () имеет значение NULL. Кажется, что исключения контекста очищаются при выполнении Razorpage. В оригинальном промежуточном программном обеспечении это как-то работает.

public class ExceptionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILoggerFactory _loggerFactory;

    public ExceptionMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
    {
        _loggerFactory = loggerFactory;
        _next = next;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        try
        {
            await _next(httpContext);
        }
        catch (Exception ex)
        {
            var logger = _loggerFactory.CreateLogger("Serilog Global exception logger");
            logger.LogError($"Something went wrong: {ex}");
            await HandleExceptionAsync(httpContext, ex);
        }
    }

    private async Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

        context.Response.Redirect("/ErrorHandling/Error");

        await Task.CompletedTask;
    }


}

Вот моя модель страницы Razor Error

 [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class ErrorModel : PageModel
{
    private ILogger<ErrorModel> _logger;
    public string RequestId { get; set; }
    public string ExceptionPath { get; set; }
    public string ExceptionMessage { get; set; }

    public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);

    public ErrorModel(ILogger<ErrorModel> logger)
    {
        _logger = logger;
    }
    public void OnGet(string executionPath)
    {
        var httpCtx = HttpContext;

        var exceptionDetails = httpCtx.Features.Get<IExceptionHandlerPathFeature>();
        if (exceptionDetails != null)
        {
            _logger.LogError(httpCtx.Response.StatusCode, exceptionDetails.Error, exceptionDetails.Error.Message);

            //Add data for view
            ExceptionPath = exceptionDetails.Path;
            ExceptionMessage = "An unexpected fault happened. Try again later.";

        }

        RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;

    }
}

После перенаправления httpCtx.Features.Get () должен вернуть объект IExceptionHandlerPathFeature, но он возвращаетNULL

1 Ответ

0 голосов
/ 25 октября 2019

Из исходного кода ExceptionHandlerMiddleware и ExceptionHandlerExtensions вам необходимо использовать перезапись вместо перенаправления.

Ниже приведен упрощенный код пользовательского ExceptionMiddleware

public class ExceptionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILoggerFactory _loggerFactory;
    public ExceptionMiddleware(
        RequestDelegate next,
        ILoggerFactory loggerFactory
    )
    {
        _next = next;
        _loggerFactory = loggerFactory;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        try
        {
            await _next(httpContext);
        }
        catch (Exception ex)
        {
            var logger = _loggerFactory.CreateLogger("Serilog Global exception logger");
            logger.LogError($"Something went wrong: {ex}");
            await HandleExceptionAsync(httpContext, ex);
        }

    }


    private async Task HandleExceptionAsync(HttpContext context, Exception ex)
    {
        PathString originalPath = context.Request.Path;
        context.Request.Path = "/Error";
        try
        {
            var exceptionHandlerFeature = new ExceptionHandlerFeature()
            {
                Error = ex,
                Path = originalPath.Value,
            };
            context.Features.Set<IExceptionHandlerFeature>(exceptionHandlerFeature);
            context.Features.Set<IExceptionHandlerPathFeature>(exceptionHandlerFeature);
            context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

            await _next(context);
            return;
        }
        catch (Exception ex2)
        {
        }
        finally
        {
            context.Request.Path = originalPath;
        }

    }
}
...