ASP.NET Coreの5つの例外処理オプション

ASP.NET Coreの5つの例外処理オプション

例外処理はプログラミングにおいて非常に重要であり、ユーザーフレンドリーなヒントを与えることができ、プログラムのセキュリティのためにも重要です。

最后更新 2021/04/29 9:27
.NET技术栈
预计阅读 3 分钟
分类
ASP.NET Core
标签
.NET C# ASP.NET Core 安全性は 異常なこと

例外処理はプログラミングにおいて非常に重要であり、ユーザーフレンドリーなヒントを与えることができ、プログラムのセキュリティのためにも重要です。ASP.NET Coreでは、デフォルトで多くのソリューションが提供されています。

1. コントローラを継承し、OnActionExecutedをオーバーライド

vs new controllerを使用すると、デフォルトではControllerクラスを継承し、OnActionExecutedをオーバーライドし、例外処理を追加します。通常、新しいBaseControllerを作成し、すべてのControllerがBaseControllerを継承するようにします。コードは以下の通り

public class BaseController : Controller
{
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        var exception = context.Exception;
        if (exception != null)
        {
            context.ExceptionHandled = true;
            context.Result = new ContentResult
            {
                Content = $"BaseController错误 : { exception.Message }"
            };
        }
        base.OnActionExecuted(context);
    }
}

この処理方法の利点はもちろん簡単ですが、欠点は明らかです。CShtmlページが間違って投げられた場合、完全にキャッチすることはできません。もちろん、プロジェクト自体がWeb APIプロジェクトであり、ビューがない場合は、これは問題ありません。

2. ActionFilterAttributeの操作

ActionFilterAttributeは、IActionFilterおよびIResultFilterを実装した機能であるため、アクションでのエラー、ビューでのエラーのいずれも、理論的にはキャプチャできます。新しいExceptionActionFilterAttributeを作成し、OnActionExecutedとOnResultExecutedを書き換え、例外処理を追加します。

public class ExceptionActionFilterAttribute:ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        var exception = context.Exception;
        if (exception != null)
        {
            context.ExceptionHandled = true;
            context.Result = new ContentResult
            {
                Content = $"错误 : { exception.Message }"
            };
        }
        base.OnActionExecuted(context);
    }

    public override void OnResultExecuted(ResultExecutedContext context)
    {
        var exception = context.Exception;
        if (exception != null)
        {
            context.ExceptionHandled = true;
            context.HttpContext.Response.WriteAsync($"错误 : {exception.Message}");
        }
        base.OnResultExecuted(context);
    }
}

利用方法は2種類あり、

  1. controllerに[TypeFilter typeof ExceptionActionFilter]ラベルを付けます。
  2. Startupではフィルターでグローバルに注入します。
services.AddControllersWithViews(options =>
{
    options.Filters.Add<ExceptionActionFilterAttribute>();
})

3. IExceptionFilterを使用する

ASP.NET Coreには5種類のフィルタがあります。IExceptionFilterはそのうちの1つです。名前が示すとおり、例外を処理するためのものです。IExceptionFilterはASP.NET CoreのExceptionFilterAttributeに実装されているため、ExceptionFilterAttributeを継承してメソッドをオーバーライドするだけです。CustomExceptionFilterAttributeもExceptionFilterAttributeを継承し、OnExceptionをオーバーライドし、例外処理を追加します。

public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        context.ExceptionHandled = true;
        context.HttpContext.Response.WriteAsync($"CustomExceptionFilterAttribute错误:{context.Exception.Message}");
        base.OnException(context);
    }
}

ExceptionFilterAttributeは非同期メソッドOnExceptionAsyncも提供しています。どちらも1つをオーバーライドするだけで済み、両方をオーバーライドすると両方のメソッドが一度実行されます。

利用方法は2種類あり、

  1. コントローラに[CustomExceptionFilter]ラベルを付けます。
  2. Startupではフィルターでグローバルに注入します。
services.AddControllersWithViews(options =>
{
    options.Filters.Add<CustomExceptionFilterAttribute>();
})

4. ExceptionHandlerの使い方

スタートアップでは、VS新規プロジェクトがデフォルトで追加されます。

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Home/Error");
}

上のコードは、開発環境がapp.UseDeveloperExceptionPage;を使用することを意味します。ホーム/エラーページに移動します。

UseDeveloperExceptionPageには、スタックトレース、クエリ、クッキー、ヘッダーなどのエラーメッセージが表示されます。net core 3.1以降は、リクエストヘッダにaccept text/htmlを追加するとhtmlページが返され、追加しないとエラーのみが返されるように変更されました。

注app.UseDeveloperExceptionPage;は先頭に配置してください。

if (!env.IsDevelopment())
 {
     app.UseDeveloperExceptionPage();
 }
 else
 {
     app.UseExceptionHandler(builder =>
     {
         builder.Run(async context =>
         {
             var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
             await context.Response.WriteAsync($"error:{exceptionHandlerPathFeature.Error.Message}");
         });
     });
 }

5. カスタムMiddleare処理

ミドルウェアで処理されます。

public class ErrorHandlingMiddleware
{
   private readonly RequestDelegate next;

   public ErrorHandlingMiddleware(RequestDelegate next)
   {
        this.next = next;
   }

   public async Task Invoke(HttpContext context)
   {
        try
        {
           await next(context);
        }
        catch (System.Exception ex)
        {
           //处理异常
        }
   }
}
Keep Exploring

延伸阅读

更多文章