为了账号安全,请及时绑定邮箱和手机立即绑定

在 ASP.NET Core MVC 中捕获异常

在 ASP.NET Core MVC 中捕获异常

C#
慕哥9229398 2022-01-09 15:19:45
我已经在 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。我在这里缺少什么?
查看完整描述

1 回答

?
米琪卡哇伊

TA贡献1998条经验 获得超6个赞

为了通知 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

{

    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(executed); // #2.

            }

            else

            {

                // NOTE: You might want to use executed here too.

                await OnAfterActionExecutionAsync(context);

            }

        }

    }


    // ...


    public virtual Task OnExceptionAsync(ActionExecutedContext context) // #1.

    {

        return Task.CompletedTask;

    }

}

public class ExceptionFilter : GenericActionFilter

{    

    public override Task OnExceptionAsync(ActionExecutedContext context) // #1, #2.

    {

        Logger.Error(context.Exception); // #2 (single parameter).


        context.Result = new ContentResult { ... };

        context.ExceptionHandled = true; // #3.


        return Task.CompletedTask;

    }

}


查看完整回答
反对 回复 2022-01-09
  • 1 回答
  • 0 关注
  • 334 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信