簡體   English   中英

在ASP.NET Core MVC中捕獲異常

[英]Catching exceptions in 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。

我在這里想念什么?

為了通知ASP.NET Core MVC管道您已處理了異常,需要將ActionExecutedContext.ExceptionHandled設置為true 因為您所顯示的代碼中沒有此內容,所以ASP.NET Core MVC管道使用其自身的錯誤處理邏輯將未處理的異常(其認為是)轉換為500響應。

現在-這個屬性存在於ActionExecutedContext而不是ActionExecutingContext (你用你的代碼)。 這是有道理的,因為ActionExecutingContext表示操作運行之前的狀態ActionExecutedContext表示操作運行之后的狀態。 這意味着您將需要進行以下更改:

  1. 更新您的OnExceptionAsync函數以使用ActionExecutedContext而不是ActionExecutingContext
  2. 更新對OnExceptionAsync的調用,以提供executed而不是context 在這里的同時,您還可以將方法參數折疊為剛剛 executed (我將在下面的代碼中顯示)。
  3. 處理完異常后,將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;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM