Asp.Net Core異常處理

本文將介紹在ASP.Net Core中處理異常的幾種方法

  • 1使用開發(fā)人員異常頁面(The developer exception page)
  • 2配置HTTP錯誤代碼頁 Configuring status code pages
  • 3使用MVC過濾器 ExceptionFilter
  • 4 自定義異常捕獲中間件 Middleware

一使用開發(fā)人員異常頁面(The developer exception page)

配置你的程序使其在發(fā)生異常時詳細的展示異常信息

  • 安裝Microsoft.AspNetCore.Diagnostics NuGet package
    .net core 2.0中包含Microsoft.AspNetCore.All,這里面包含了Microsoft.AspNetCore.Diagnostics暑脆,無需自安裝土匀。
  • 在Startup.cs 上添加對exception page的使用Configure method in the Startup class:
public void Configure(IApplicationBuilder app)
{    
        app.UseDeveloperExceptionPage();//使用異常記錄頁面
}

在控制器中拋一個異常:

   public class HomeController : Controller
    {
      
        public IActionResult Index()
        {         
            throw new Exception();
            return View();
        }
    }

在開發(fā)環(huán)境下運行,異常展示頁面包含幾個標簽展示異常信息和HTTP請求。第一個選項卡包含一個堆棧跟蹤


image.png

它下一個選項卡顯示查詢字符串參數(shù),如果有的話。


image.png

第三個是Cookies和Headers信息


image.png

提示:在任何你想要捕捉異常的中間件(middleware)之前注冊UseDeveloperExceptionPage 比如 app.UseMvc.

一般在項目開發(fā)中筐带,UseDeveloperExceptionPage展示異常詳情信息對開發(fā)過程很有幫助,但在項目發(fā)布出去以后扣孟,在系統(tǒng)發(fā)生異常時更明智的是向用戶展示一個靜態(tài)的錯誤頁面烫堤。這時就要做如下更改了:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
   //判斷是否是開發(fā)環(huán)境
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/error");
    }

依據(jù)上面代碼,app.UseExceptionHandler("/error");在生產環(huán)境下凤价,發(fā)生系統(tǒng)錯誤時,跳轉到錯誤頁面

二配置HTTP錯誤代碼頁 Configuring status code pages

如果訪問項目上一個不存在的頁面拔创,會如下顯示:


image.png

修改 Startup.Configure利诺,使其能夠使用HTTP錯誤代碼頁

       public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                //開發(fā)環(huán)境異常處理
                app.UseBrowserLink();
                app.UseDeveloperExceptionPage();
            }
            else
            {
                //生產環(huán)境異常處理
                app.UseExceptionHandler("/Home/Error");
            }
            app.UseStatusCodePages();//使用HTTP錯誤代碼頁
        }

再次訪問不存在的頁面


image.png

app.UseStatusCodePages支持多種擴展方法。其中一個方法接受一個lambda表達式:

app.UseStatusCodePages(async context =>
{
    context.HttpContext.Response.ContentType = "text/plain";
    await context.HttpContext.Response.WriteAsync(
        "Status code page, status code: " + 
        context.HttpContext.Response.StatusCode);
});

還可以跳轉到指定頁面剩燥,并附加Response.StatusCode

app.UseStatusCodePagesWithReExecute("/Home/Error/{0}");
占位符{0}在這代表Response.StatusCode 如:404

image.png

三使用MVC過濾器

// <summary>
    /// 自定義全局異常過濾器
    /// </summary>
    public class GlobalExceptionFilter : IExceptionFilter
    {
       
        readonly ILoggerFactory _loggerFactory;//采用內置日志記錄
        readonly IHostingEnvironment _env;//環(huán)境變量
        public GlobalExceptionFilter(ILoggerFactory loggerFactory, IHostingEnvironment env)
        {
            _loggerFactory = loggerFactory;
            _env = env;
        }

        public void OnException(ExceptionContext context)
        {
            var controller = context.ActionDescriptor;          
            ILog log = LogManager.GetLogger(Startup.Repository.Name, controller.ToString());//初始化Log4net日志
            #region 記錄到內置日志
            //var logger = _loggerFactory.CreateLogger(context.Exception.TargetSite.ReflectedType);
            //logger.LogError(new EventId(context.Exception.HResult),
            //context.Exception,
            //context.Exception.Message);
            #endregion
            if (_env.IsDevelopment())
            {
                log.Error(context.Exception.ToString());
                //var JsonMessage = new ErrorResponse("未知錯誤,請重試");
                //JsonMessage.DeveloperMessage = context.Exception;
                //context.Result = new ApplicationErrorResult(JsonMessage);
                //context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                //context.ExceptionHandled = true;
            }
            else
            {
                log.Error(context.Exception.ToString());
                context.ExceptionHandled = true;
                context.Result=new RedirectResult("/home/Error");
            }
        }
        public class ApplicationErrorResult : ObjectResult
        {
            public ApplicationErrorResult(object value) : base(value)
            {
                StatusCode = (int)HttpStatusCode.InternalServerError;
            }
        }
        public class ErrorResponse
        {
            public ErrorResponse(string msg)
            {
                Message = msg;
            }
            public string Message { get; set; }
            public object DeveloperMessage { get; set; }
        }
    }
}

使用OnException方法慢逾,當異常發(fā)生時,調用這個方法灭红。
在上面代碼中侣滩,根據(jù)項目環(huán)境的不同,分開處理異常变擒。

  • 當開發(fā)環(huán)境中君珠,通過Log4net把日志記錄到本地文件中。再這里注釋了一句很重要代碼context.ExceptionHandled = true;//代表異常已經處理娇斑,context.ExceptionHandled 代表異常是否處理策添,不是true時材部,異常記錄到日志文件中后,系統(tǒng)對異常的處理并未結束唯竹,如果這時系統(tǒng)使用了開發(fā)人員異常頁面(The developer exception page),系統(tǒng)在頁面上詳細展示系統(tǒng)異常信息乐导。若果context.ExceptionHandled為true,異常通過Log4net把日志記錄到本地文件后浸颓,系統(tǒng)對異常的處理就結束了物臂。

    開發(fā)環(huán)境下異常展示.gif

  • 生產環(huán)境下,通過Log4net把日志記錄到本地文件中后产上,context.ExceptionHandled = true;系統(tǒng)處理異常結束棵磷,讓系統(tǒng)跳轉到靜態(tài)錯誤頁。


    生產環(huán)境下異常展示.gif

四自定義異常捕獲中間件 Middleware

對于一些非MVC引起的異常蒂秘,MVC過濾器是不能捕獲異常的泽本。

什么是中間件?

中間件是一種組裝到系統(tǒng)應用程序的請求管道用來處理請求和相應的框架。它的各個構成:
1) 在程序管道中是否選擇將請求傳遞給下一個組件姻僧。
2)可以在系統(tǒng)請求管道的下一個中間件的執(zhí)行的前面或者后面處理請求和相應
一個委托請求被用來構建請求管道规丽。這個委托請求用來處理每一個HTTP請求。
委托請求使用方法Run,Map 和使用Use方法的擴展方法來配置
自己可以指定創(chuàng)建一個匿名的委托請求in-iline撇贺,也可以將將其定義在一個可重用的類里面赌莺。
這些可重用的類和in-line匿名方法就稱為中間件,或者中間組件。
在請求管道中的每一個中間件的任務就是調用下一個中間件松嘶,特定場景下也可以越過下一個中間件直接返回結果艘狭。
下面是一個自定義ExceptionHandlingMiddleware中間件的過程,當捕獲到異常時翠订,存到日志中巢音。

    /// <summary>
    /// 自定義異常處理中間件
    /// </summary>
    public class ExceptionHandlingMiddleware
    {
        private readonly RequestDelegate _next;

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

        public async Task Invoke(HttpContext context)
        {
            try
            {
                await _next(context);
            }
            catch (Exception ex)
            {
                var statusCode = context.Response.StatusCode;
                await HandleExceptionAsync(context, ex.ToString());            
            }        
        }
        private Task HandleExceptionAsync(HttpContext context,  string msg)
        {          
            HandleExceptionHelper hannd = new HandleExceptionHelper();
            hannd.log.Error(msg);//記錄到日志文件
            return context.Response.WriteAsync("ERROR");
        }
    }

在定義一個異常的中間件,并拋一個異常尽超,用ExceptionHandlingMiddleware捕獲異常

 app.Use(async (context, next) =>
            {
                throw new Exception();              
                await next.Invoke();              
            });
image.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末官撼,一起剝皮案震驚了整個濱河市纷捞,隨后出現(xiàn)的幾起案子褪贵,更是在濱河造成了極大的恐慌,老刑警劉巖压固,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巩踏,死亡現(xiàn)場離奇詭異秃诵,居然都是意外死亡,警方通過查閱死者的電腦和手機塞琼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門菠净,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事嗤练¢涣耍” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵煞抬,是天一觀的道長霜大。 經常有香客問我,道長革答,這世上最難降的妖魔是什么战坤? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮残拐,結果婚禮上途茫,老公的妹妹穿的比我還像新娘。我一直安慰自己溪食,他們只是感情好囊卜,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著错沃,像睡著了一般栅组。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上枢析,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天玉掸,我揣著相機與錄音,去河邊找鬼醒叁。 笑死司浪,一個胖子當著我的面吹牛,可吹牛的內容都是我干的把沼。 我是一名探鬼主播啊易,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼饮睬!你這毒婦竟也來了认罩?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤续捂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后宦搬,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體牙瓢,經...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年间校,在試婚紗的時候發(fā)現(xiàn)自己被綠了矾克。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡憔足,死狀恐怖胁附,靈堂內的尸體忽然破棺而出酒繁,到底是詐尸還是另有隱情,我是刑警寧澤控妻,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布州袒,位于F島的核電站,受9級特大地震影響弓候,放射性物質發(fā)生泄漏郎哭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一菇存、第九天 我趴在偏房一處隱蔽的房頂上張望夸研。 院中可真熱鬧,春花似錦依鸥、人聲如沸亥至。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姐扮。三九已至,卻和暖如春关筒,著一層夾襖步出監(jiān)牢的瞬間溶握,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工蒸播, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留睡榆,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓袍榆,卻偏偏與公主長得像胀屿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子包雀,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內容

  • 1. ASP.NET Core 異常處理與日志記錄[#1-aspnet-core-%E5%BC%82%E5%B8%...
    xdpie閱讀 2,976評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理宿崭,服務發(fā)現(xiàn),斷路器才写,智...
    卡卡羅2017閱讀 134,599評論 18 139
  • 六種異常處理的陋習 你覺得自己是一個Java專家嗎葡兑?是否肯定自己已經全面掌握了Java的異常處理機制?在下面這段代...
    Executing閱讀 1,316評論 0 6
  • 轉載至:http://www.cnblogs.com/cvst/p/5822373.html Java Excep...
    小沙鷹168閱讀 1,890評論 0 3
  • 燦爛的陽光穿過樹葉間的空隙赞草,透過早霧讹堤,一縷縷地灑滿了校園,合肥特教中心春季運動會如期而至厨疙。 上圖:
    Camisa閱讀 247評論 0 0