溫馨提示×

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

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

在 ASP.NET Web API 中使用 Attribute 統(tǒng)一處理異常

發(fā)布時(shí)間:2020-08-06 00:21:39 來源:網(wǎng)絡(luò) 閱讀:1078 作者:smobiler 欄目:編程語言

并非所有的異常都需要 try-catch 進(jìn)行重復(fù)的處理,這會(huì)導(dǎo)致大量的重復(fù)性代碼,一旦后續(xù)系統(tǒng)出現(xiàn)異常處理機(jī)制的修改,隨著代碼量增多,修改也會(huì)變的更加困難。

ASP.NET Web API 中特別增加了全局異常過濾器功能,諸如于此的還有很多過濾器可供開發(fā)者選擇,以實(shí)現(xiàn)面向切面編程,它們?cè)谌〈貜?fù)性編碼這一目標(biāo)的路上,作出很多貢獻(xiàn),同時(shí)降低了后期維護(hù)代碼的難度,提升了可讀性。

大多數(shù)異常處理的 try-catch 都通常是同樣的寫法(記錄異常日志、返回錯(cuò)誤信息等),因此我們可以將他們統(tǒng)一寫在一個(gè)過濾器中,讓 API 在出現(xiàn)異常時(shí),即使沒有使用 try-catch 嵌套異常位置和解決方案,也能夠自動(dòng)進(jìn)入期望的異常處理方法。


注意:這是專門針對(duì) Web API 所使用的全局異常處理器。如果是 Controller,則它有另外一套全局異常處理機(jī)制,因?yàn)橥ǔG闆r下 MVC 的控制器不只返回Json字符串,通常要涉及頁(yè)面View,文件File,Json字符串等。


Get Start

下面我們以一個(gè)最簡(jiǎn)單的異常處理過濾器代碼為例,來說明應(yīng)當(dāng)如何使全局異常處理器生效:


1.創(chuàng)建一個(gè)類 MyExceptionFilterAttribute,繼承 ExceptionFilterAttribute, System.Web.Mvc.IExceptionFilter 并實(shí)現(xiàn)接口方法


using Newtonsoft.Json;
using System.Net.Http;
using System.Web.Http.Filters;
using System.Web.Mvc;

namespace WebAPITest.Filters
{
???? public class MyExceptionFilterAttribute : ExceptionFilterAttribute, System.Web.Mvc.IExceptionFilter
???? {
???????? //MVC過濾器要求必須繼承此接口才允許注冊(cè),但我們可以繼承、實(shí)現(xiàn)但不寫它。
???????? public void OnException(ExceptionContext filterContext)
???????? {
???????????? throw new NotImplementedException();
???????? }

??????? //真正能讓API全局異常過濾器在出現(xiàn)異常時(shí)生效的是這個(gè)家伙:
???????? public override void OnException(HttpActionExecutedContext actionExecutedContext)
???????? {
???????????? base.OnException(actionExecutedContext);

??????????? actionExecutedContext.Response = new HttpResponseMessage() { Content = new StringContent("出現(xiàn)異常") };
???????????? return;

??????? }

}



2.為此全局異常處理器進(jìn)行注冊(cè):

打開文件夾 App_Start 下的 FilterConfig.cs 為過濾器注冊(cè),由此才能使得過濾器生效。


特別說明:一旦進(jìn)行了全局注冊(cè),則所有方法出現(xiàn)異常時(shí),過濾器都會(huì)生效。


public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
???? filters.Add(new MyExceptionFilterAttribute());
}



作為特性標(biāo)簽使用

當(dāng)然,上述 MyExceptionFilterAttribute 除了可注冊(cè)為全局異常過濾器以外,也可以單獨(dú)為 API 中的某些方法使用:(注意,方法本身就是"try",過濾器是"catch"。所以不再需要在方法體內(nèi)再次 try-catch)

using System.Net.Http;
using System.Web.Http;
using WebAPITest.Filters;
using WebAPITest.Models;

namespace WebAPITest.Controllers
{
???? //你也可以把過濾器標(biāo)簽打在這個(gè)地方,這代表該API類下的所有接口均接受[MyExceptionFilter]接管異常處理。
???? public class TestController : ApiController
???? {
???????? [MyExceptionFilter]???? //特性標(biāo)簽打在此處,則 UserException 方法出現(xiàn)異常時(shí)會(huì)觸發(fā) MyExceptionFilterAttribute 中的異常處理方法。
???????? public HttpResponseMessage UserException()
???????? {
???????????? throw new UserException("用戶異常");
???????? }

??????? [MyExceptionFilter]???? //同上,這一特性標(biāo)簽將幫助 SystemException 方法處理異常。
???????? public HttpResponseMessage SystemException()
???????? {
???????????? throw new Exception();
???????? }

??? }
}



標(biāo)簽與全局注冊(cè)的優(yōu)先級(jí)問題

多個(gè)特性標(biāo)簽,可以全局注冊(cè),可以單獨(dú)在方法名稱上、類名上混合使用,那么如果一個(gè)標(biāo)簽被全局注冊(cè),另一個(gè)標(biāo)簽被單獨(dú)打在方法名上或者類名上,則最終哪一個(gè)處理器的方法會(huì)被觸發(fā)?

這些家伙的優(yōu)先級(jí)其實(shí)和 css 層疊樣式表的優(yōu)先級(jí)相仿。

即:如果我們?nèi)肿?cè)過一個(gè)過濾器A,又在 ApiController 類的最頂端打了另外一個(gè)B、又在Action方法上打了第三個(gè)異常處理器C,那么默認(rèn)只會(huì)執(zhí)行最靠近 Action 的C處理器,也就是說:ActionFilter > ClassFilter > GlobalFilter。

另外如果需要多次執(zhí)行全部生效,即:全局一次,Controller類一次,Action一次,那么則需要為過濾器頂端加那么一個(gè)標(biāo)簽 [AttributeUsage(AttributeTargets.All,AllowMultiple = true)],然后當(dāng)異常觸發(fā)時(shí),他們就能夠支持多次執(zhí)行。

當(dāng)然,真正的異常處理還會(huì)涉及很多復(fù)雜的內(nèi)容,這只是一個(gè)概覽。例如返回值需要被標(biāo)準(zhǔn)化(包含狀態(tài)碼、消息、響應(yīng)流等內(nèi)容),調(diào)用異常處理工具向服務(wù)器發(fā)送異常信息記錄,記錄請(qǐng)求參數(shù),對(duì)GET/POST請(qǐng)求導(dǎo)致異常的差異化處理方法等。

但我們?cè)谶@里提供的是一個(gè)思路,讓你知道,精簡(jiǎn)代碼、提升開發(fā)效率其實(shí)可以有更多的方法和可能性。而不必非要使用同一種方式,當(dāng)你覺得某些步驟一直在不斷重復(fù),則應(yīng)當(dāng)已經(jīng)有早期的開發(fā)者給出了解決方案,而你需要去發(fā)現(xiàn)他們。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI