在 ASP.NET Core MVC 中捕获异常

我已经在 ASP.NET MVC Core 中看到了多种捕获异常的方法,但我需要了解为什么我所做的没有按预期工作。


我添加了以下内容:


public abstract class GenericActionFilter : ActionFilterAttribute

{

    protected readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);



    public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)

    {

        if (await OnBeforeActionExecutionAsync(context))

        {

            var executed = await next();


            if (executed.Exception != null && !executed.ExceptionHandled)

            {

                await OnExceptionAsync(context, executed.Exception);

            }

            else

            {

                await OnAfterActionExecutionAsync(context);

            }

        }

    }


    public virtual Task<bool> OnBeforeActionExecutionAsync(ActionExecutingContext context)

    {

        return Task.FromResult(true);

    }


    public virtual Task OnAfterActionExecutionAsync(ActionExecutingContext context)

    {

        return Task.CompletedTask;

    }


    public virtual Task OnExceptionAsync(ActionExecutingContext context, Exception ex)

    {

        return Task.CompletedTask;

    }

}

并像这样使用它:


public class ExceptionFilter : GenericActionFilter

{

    public IntegrationScenarioSettings Settings { get; set; }



    public override Task OnExceptionAsync(ActionExecutingContext context, Exception ex)

    {

        context.Result = new ContentResult

        {

            Content = Settings.ApiExecutionExceptionMessage,

            StatusCode = (int)HttpStatusCode.ServiceUnavailable

        };


        //outputs to endpoint.log

        Logger.Error(ex);


        return Task.CompletedTask;

    }

}

动作中的底层代码抛出异常,而不是看到 503,我仍然是 500。


我在这里缺少什么?


慕哥9229398
浏览 335回答 1
1回答

米琪卡哇伊

为了通知 ASP.NET Core MVC 管道您已处理异常,您需要设置ActionExecutedContext.ExceptionHandled为true. 因为您在显示的代码中没有此功能,所以 ASP.NET Core MVC 管道使用其自己的错误处理逻辑将您的(它认为是)未处理的异常转换为 500 响应。现在 - 此属性存在于ActionExecutedContext而不是ActionExecutingContext(您在代码中使用)。这是有道理的,因为它ActionExecutingContext代表了动作运行之前的状态,也代表了动作运行之后的ActionExecutedContext状态。这意味着您将需要以下一组更改:更新你的OnExceptionAsync函数来ActionExecutedContext代替ActionExecutingContext.更新对 的调用OnExceptionAsync,提供executed而不是context。当您在这里时,您还可以将方法参数折叠为仅 executed(我将在下面的代码中显示)。设置context.ExceptionHandled为true一旦你已经处理了异常。:)我已经从您的问题中获取了代码,删除了一些与问题无关的代码并应用了这些更改,我用上面的相应数字调用了这些更改:public abstract class GenericActionFilter : ActionFilterAttribute{&nbsp; &nbsp; public override async Task OnActionExecutionAsync(ActionExecutingContext context,&nbsp; &nbsp; &nbsp; &nbsp; ActionExecutionDelegate next)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (await OnBeforeActionExecutionAsync(context))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var executed = await next();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (executed.Exception != null && !executed.ExceptionHandled)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await OnExceptionAsync(executed); // #2.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // NOTE: You might want to use executed here too.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await OnAfterActionExecutionAsync(context);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; // ...&nbsp; &nbsp; public virtual Task OnExceptionAsync(ActionExecutedContext context) // #1.&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return Task.CompletedTask;&nbsp; &nbsp; }}public class ExceptionFilter : GenericActionFilter{&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; public override Task OnExceptionAsync(ActionExecutedContext context) // #1, #2.&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; Logger.Error(context.Exception); // #2 (single parameter).&nbsp; &nbsp; &nbsp; &nbsp; context.Result = new ContentResult { ... };&nbsp; &nbsp; &nbsp; &nbsp; context.ExceptionHandled = true; // #3.&nbsp; &nbsp; &nbsp; &nbsp; return Task.CompletedTask;&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP