91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ASP.NET?Core全局異常處理方法是什么

發布時間:2022-03-28 09:13:15 來源:億速云 閱讀:678 作者:iii 欄目:開發技術

這篇“ASP.NET Core全局異常處理方法是什么”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“ASP.NET Core全局異常處理方法是什么”文章吧。

一、前言

在程序設計中,我們會遇到各種各樣的異常問題,一個好的異常處理解決方案能夠幫助開發者快速的定位問題,也能夠給用戶更好的用戶體驗。那么我們在AspNetCore中該如何捕獲和處理異常呢?我們以一個WebApi項目為例,講解如何捕獲和處理異常。

二、異常處理

1、異常處理

開發過ASP.NET程序的人都知道:IExceptionFilter。這個過濾器同樣在AspNetCore中也可以用來捕獲異常。不過,對于使用IExceptionFilter,更建議使用它的異步版本:IAsyncExceptionFilter。那么該如何使用過濾器呢?下面以IAsyncExceptionFilter為例,對于同步版本其實也是一樣的。

我們在項目中添加一個Model文件夾,存放返回結果實體類,這里定義一個泛型類:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ExceptionDemo.Model
{
    public class ResultModel<T>
    {
        /// <summary>
        /// 返回結果編碼 0:失敗 1:成功
        /// </summary>
        public int ResultCode { get; set; }

        /// <summary>
        /// 返回結果內容 成功:Success  失敗:異常內容
        /// </summary>
        public string ResultMsg { get; set; }

        /// <summary>
        /// 返回結果 成功:返回T類型數據 失敗:默認null
        /// </summary>
        public T ResultData { get; set; }
    }
}

我們在項目中添加一個Filter文件夾,所有的過濾器都放在該文件夾下面。然后添加一個類:CustomerExceptionFilter,并使該類繼承自IAsyncExceptionFilter。代碼如下:

using ExceptionDemo.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using System.Threading.Tasks;

namespace ExceptionDemo.Filter
{
    /// <summary>
    /// 自定義異常過濾器
    /// </summary>
    public class CustomerExceptionFilter : IAsyncExceptionFilter
    {
        /// <summary>
        /// 重寫OnExceptionAsync方法,定義自己的處理邏輯
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task OnExceptionAsync(ExceptionContext context)
        {
            // 如果異常沒有被處理則進行處理
            if(context.ExceptionHandled==false)
            {
                // 定義返回類型
                var result = new ResultModel<string>
                {
                    ResultCode = 0,
                    ResultMsg = context.Exception.Message
                };
                context.Result = new ContentResult
                {
                    // 返回狀態碼設置為200,表示成功
                      StatusCode = StatusCodes.Status200OK,
                      // 設置返回格式
                      ContentType="application/json;charset=utf-8",
                      Content=JsonConvert.SerializeObject(result)
                };
            }
            // 設置為true,表示異常已經被處理了
            context.ExceptionHandled = true;
            return Task.CompletedTask;
        }
    }
}

上面的代碼很簡單,我們新建了一個自定義的異常過濾器,然后在OnExceptionAsync方法中定義自己的處理邏輯,報錯之后依然讓http返回狀態碼為200,并且將錯誤信息返回到客戶端。

然后添加一個控制器,命名為ExceptionFilter,在控制器中模擬發生異常的情況:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ExceptionDemo.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace ExceptionDemo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ExceptionFilterController : ControllerBase
    {
        [HttpGet]
        public async Task<ResultModel<int>> Get()
        {
            int i = 0;
            int k = 10;
            // 這里會發生異常
            int j = await Task.Run<int>(() => 
            {
                return k / i;
            });


            return new ResultModel<int>()
            {
                ResultCode=1,
                ResultMsg="Success",
                ResultData=j
            };
        }
    }
}

最后我們需要把自定義的異常過濾器進行注入,這里選擇使用全局注入的方式,在Startup類的ConfigureServices方法中進行注入:

services.AddControllers(options => 
{
      options.Filters.Add(new CustomerExceptionFilter());
});

然后運行程序,查看結果:

ASP.NET?Core全局異常處理方法是什么

如何我們沒有使用過濾器捕獲和處理異常,我們將得到Http狀態碼為500的內部錯誤,這種錯誤不方便定位問題,而且給客戶端返回的信息也不夠友好。使用了過濾器處理異常,進行特殊處理之后就會顯得很友好了。

在上面自定義過濾器的代碼中,有下面的一行代碼:

context.ExceptionHandled = true;

注意:這句代碼很關鍵,當你處理完異常之后,一定要將此屬性更改為true,表示異常已經處理過了,這樣其他地方就不會在處理這個異常了。 

2、使用中間件處理異常

我們知道,AspNetCore的管道模型具有層層傳遞的特點,那么我們就可以在管道中實現全局異常捕獲。我們新創建一個自定義的異常中間件:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Text.Json;
using System.Threading.Tasks;

namespace ExceptionDemo.Middleware
{
    /// <summary>
    /// 自定義異常中間件
    /// </summary>
    public class CustomerExceptionMiddleware
    {
        /// <summary>
        /// 委托
        /// </summary>
        private readonly RequestDelegate _next;

        public CustomerExceptionMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            try
            {
                await _next(context);
            }
            catch (Exception ex)
            {

                context.Response.ContentType = "application/problem+json";

                var title = "An error occured: " + ex.Message;
                var details = ex.ToString();

                var problem = new ProblemDetails
                {
                    Status = 200,
                    Title = title,
                    Detail = details
                };

                var stream = context.Response.Body;
                await JsonSerializer.SerializeAsync(stream, problem);
            }
        }
    }
}

然后在新建一個擴展方法:

using Microsoft.AspNetCore.Builder;

namespace ExceptionDemo.Middleware
{
    /// <summary>
    /// 靜態類
    /// </summary>
    public static class ExceptionMiddlewareExtension
    {
        /// <summary>
        /// 靜態方法
        /// </summary>
        /// <param name="app">要進行擴展的類型</param>
        public static void UseExceptionMiddleware(this IApplicationBuilder app)
        {
            app.UseMiddleware(typeof(CustomerExceptionMiddleware));
        }
    }
}

最后在Startup類的Configure方法中使用自定義的異常中間件:

app.UseExceptionMiddleware();

然后我們注釋掉上面注冊的異常過濾器,運行程序進行訪問:

ASP.NET?Core全局異常處理方法是什么

這樣也可以捕獲到異常。

3、使用框架自帶異常中間件

 我們首先看下面一段代碼:

if (env.IsDevelopment())
{
       app.UseDeveloperExceptionPage();
}

這段代碼在我們使用AspNetCore創建一個WebApi項目時就會看到,如果是創建的MVC項目,是下面一段代碼:

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

這兩段代碼的作用就是捕獲和處理異常,是第一個被添加到管道中的中間件。

UseDeveloperExceptionPage的意思很好理解:對于開發模式,一旦報錯就跳轉到錯誤堆棧頁面。而第二個UseExceptionHandler也很有意思,從它的名字中我們大致可以猜出它肯定是個錯誤攔截程序。那么它和上面自定義的異常處理中間件有什么區別呢?

UseExceptionHandler其實就是默認的錯誤處理。它其實也是一個中間件,它的原名叫做ExceptionHandlerMiddleware。在使用UseExceptionHandler方法時,我們可以選填各種參數。比如上面的第二段代碼,填入了“/Error”參數,表示當產生異常的時候,將定位到對應的路徑,這里定位的頁面就是“http://localhost:5001/Error”。這是MVC中自帶的一個錯誤頁面,當然,你也可以指定自己定義的一個頁面。

UseExceptionHandler還有一個指定ExceptionHandlerOptions參數的擴展方法,該參數是ExceptionHandlerMiddleware中間件的重要參數:

參數名說明
ExceptionHandlingPath重定向的路徑,比如剛才的 ""/Error"" 實際上就是指定的該參數
ExceptionHandler錯誤攔截處理程序

ExceptionHandler允許我們在ExceptionHandlerMiddleware內部指定咱們自己的異常處理邏輯。而該參數的類型為RequestDelegate類型的委托。因此,UseExceptionHandler提供了一個簡便的寫法,可以讓我們在ExceptionHandlerMiddleware中新建自定義的錯誤攔截管道來處理異常:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using ExceptionDemo.Filter;
using ExceptionDemo.Middleware;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace ExceptionDemo
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            #region 注冊全局異常過濾器
            //services.AddControllers(options => 
            //{
            //    options.Filters.Add(new CustomerExceptionFilter());
            //});
            #endregion

            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler(builder => builder.Use(ExceptionHandlerDemo));
            }

            
            app.UseExceptionMiddleware();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

        private async Task ExceptionHandlerDemo(HttpContext httpContext,Func<Task> next)
        {
            //該信息由ExceptionHandlerMiddleware中間件提供,里面包含了ExceptionHandlerMiddleware中間件捕獲到的異常信息。
            var exceptionDetails = httpContext.Features.Get<IExceptionHandlerFeature>();
            var ex = exceptionDetails?.Error;

            if (ex != null)
            {
                httpContext.Response.ContentType = "application/problem+json";

                var title = "An error occured: " + ex.Message;
                var details = ex.ToString();

                var problem = new ProblemDetails
                {
                    Status = 500,
                    Title = title,
                    Detail = details
                };

                var stream = httpContext.Response.Body;
                await JsonSerializer.SerializeAsync(stream, problem);
            }
        }
    }
}

三、中間件和過濾器的比較

在上面的例子中,我們分別使用了中間件和過濾器的方式來處理異常,那么中間件和過濾器有什么區別呢?兩者的區別:攔截范圍的不同。

ASP.NET?Core全局異常處理方法是什么

IExceptionFilter作為一種過濾器,它需要在控制器發現錯誤之后將錯誤信息提交給它處理,因此它的異常處理范圍是控制器內部。如果我們想捕獲進入控制器之前的一些錯誤,IExceptionFilter是捕獲不到的。而對于ExceptionHandlerMiddleware異常中間件來說就很容易了,它作為第一個中間件被添加到管道中,在它之后發生的任何異常都可以捕獲的到。

那么為什么要有兩種異常處理的方式呢?只使用ExceptionHandlerMiddleware中間件處理異常不可以嗎?它可以捕獲任何時候發生的異常,為什么還要有過濾器呢?如果你想在控制器發生異常時快速捕獲和處理異常,那么使用過濾器處理異常是非常不錯的選擇。如果是控制器內部發生了異常,首先是由過濾器捕獲到異常,最后才是中間件捕獲到異常。

我們在自定義過濾器的時候有這樣一段代碼:context.ExceptionHandled = true;如果在自定義過濾器中將異常標記為已經處理之后,則第一個異常處理中間件就認為沒有錯誤了,不會進入到處理邏輯中了。所以,如果不把 ExceptionHandled屬性設置為true,可能出現異常處理結果被覆蓋的情況。

以上就是關于“ASP.NET Core全局異常處理方法是什么”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

昭通市| 崇州市| 东阿县| 青铜峡市| 苍南县| 漯河市| 扶沟县| 增城市| 合肥市| 洪洞县| 黔南| 衡东县| 菏泽市| 平山县| 滨州市| 玛曲县| 平舆县| 买车| 宜丰县| 香港| 济阳县| 甘肃省| 博爱县| 个旧市| 乌兰县| 桓仁| 衡水市| 乌拉特前旗| 望城县| 安陆市| 临澧县| 武城县| 金坛市| 柳林县| 吉木萨尔县| 肃北| 安图县| 呼伦贝尔市| 汝阳县| 大同县| 商水县|