最近在整理優(yōu)化.net代碼時(shí),發(fā)現(xiàn)幾個(gè)很不友好的處理現(xiàn)象:登錄判斷、權(quán)限認(rèn)證、日志記錄、異常處理等通用操作,在項(xiàng)目中的action中到處都是。在代碼優(yōu)化上,這一點(diǎn)是很重要著力點(diǎn)。這時(shí).net中的過(guò)濾器、攔截器(Filter)就派上用場(chǎng)了。現(xiàn)在根據(jù)這幾天的實(shí)際工作,對(duì)其做了一個(gè)簡(jiǎn)單的梳理,分享出來(lái),以供大家參考交流,如有寫的不妥之處,多多指出,多多交流。
概述:
.net中的Filter中主要包括以下4大類:Authorize(授權(quán)),ActionFilter(自定義),HandleError(錯(cuò)誤處理)。
過(guò)濾器 |
類名 |
實(shí)現(xiàn)接口 |
描述 |
授權(quán) |
AuthorizeAttribute |
IAuthorizationFilter |
此類型(或過(guò)濾器)用于限制進(jìn)入控制器或控制器的某個(gè)行為方法,比如:登錄、權(quán)限、訪問(wèn)控制等等 |
異常 |
HandleErrorAttribute |
IExceptionFilter |
用于指定一個(gè)行為,這個(gè)被指定的行為處理某個(gè)行為方法或某個(gè)控制器里面拋出的異常,比如:全局異常統(tǒng)一處理。 |
自定義 |
ActionFilterAttribute |
IActionFilter和IResultFilter |
用于進(jìn)入行為之前或之后的處理或返回結(jié)果的之前或之后的處理,比如:用戶請(qǐng)求日志詳情日志記錄 |
AuthorizeAttribute:認(rèn)證授權(quán)
認(rèn)證授權(quán)主要是對(duì)所有action的訪問(wèn)第一入口認(rèn)證,對(duì)用戶的訪問(wèn)做第一道監(jiān)管過(guò)濾攔截閘口。
實(shí)現(xiàn)方式:需要自定義一個(gè)類,繼承AuthorizeAttribute并重寫OnAuthorization,在OnAuthorization中能夠獲取到用戶請(qǐng)求的所有Request信息,其實(shí)我們做的所有認(rèn)證攔截操作,其所有數(shù)據(jù)支撐都是來(lái)自Request中。
具體驗(yàn)證流程設(shè)計(jì):
IP白名單:這個(gè)主要針對(duì)的是API做IP限制,只有指定IP才可訪問(wèn),非指定IP直接返回
請(qǐng)求頻率控制:這個(gè)主要是控制用戶的訪問(wèn)頻率,主要是針對(duì)API做,超出請(qǐng)求頻率直接返回。
登錄認(rèn)證:登錄認(rèn)證一般我們采用的是通過(guò)在請(qǐng)求的header中傳遞token的方式來(lái)進(jìn)行驗(yàn)證,這樣即使用與一般的MVC登錄認(rèn)證,也使用與API接口的Auth認(rèn)證,并且也不依賴于用戶前端js設(shè)置等。
授權(quán)認(rèn)證:授權(quán)認(rèn)證就簡(jiǎn)單了,主要是驗(yàn)證該用戶是否具有該權(quán)限,如果不具有,直接做下相應(yīng)的返回處理。
MVC和API異同:
命名空間:MVC:System.Web.Http.Filters;API:System.Web.Mvc
注入方式:在注入方式上,主要包括:全局->控制器Controller->行為Action
全局注冊(cè):針對(duì)所有系統(tǒng)的所有Aciton都使用
Controller:只針對(duì)該Controller下的Action起作用
Action:只針對(duì)該Action起作用
其中全局注冊(cè),針對(duì)MVC和API還有一些差異:
MVC在 FilterConfig.cs中注入
1
|
filters.Add( new XYHMVCAuthorizeAttribute()); |
API 在 WebApiConfig.cs 中注入
1
|
config.Filters.Add( new XYHAPIAuthorizeAttribute()); |
注意事項(xiàng):在實(shí)際使用中,針對(duì)認(rèn)證授權(quán),我們一般都是添加全局認(rèn)證,但是,有的action又不需要做認(rèn)證,比如本來(lái)的登錄Action等等,那么該如何排除呢?其實(shí)也很簡(jiǎn)單,我們只需要在自定定義一個(gè)Attribute集成Attribute,或者系統(tǒng)的AllowAnonymousAttribute,在不需要驗(yàn)證的action中只需要注冊(cè)上對(duì)于的Attribute,并在驗(yàn)證前做一個(gè)過(guò)濾即可,比如:
1
2
3
4
5
|
// 有 AllowAnonymous 屬性的接口直接開(kāi)綠燈 if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any()) { return ; } |
API AuthFilterAttribute實(shí)例代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
/// <summary> /// 授權(quán)認(rèn)證過(guò)濾器 /// </summary> public class XYHAPIAuthFilterAttribute : AuthorizationFilterAttribute { /// <summary> /// 認(rèn)證授權(quán)驗(yàn)證 /// </summary> /// <param name="actionContext">請(qǐng)求上下文</param> public override void OnAuthorization(HttpActionContext actionContext) { // 有 AllowAnonymous 屬性的接口直接開(kāi)綠燈 if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any()) { return ; } // 在請(qǐng)求前做一層攔截,主要驗(yàn)證token的有效性和驗(yàn)簽 HttpRequest httpRequest = HttpContext.Current.Request; // 獲取apikey var apikey = httpRequest.QueryString[ "apikey" ]; // 首先做IP白名單校驗(yàn) MBaseResult< string > result = new AuthCheckService().CheckIpWhitelist(FilterAttributeHelp.GetIPAddress(actionContext.Request), apikey); // 檢驗(yàn)時(shí)間搓 string timestamp = httpRequest.QueryString[ "Timestamp" ]; if (result.Code == MResultCodeEnum.successCode) { // 檢驗(yàn)時(shí)間搓 result = new AuthCheckService().CheckTimestamp(timestamp); } if (result.Code == MResultCodeEnum.successCode) { // 做請(qǐng)求頻率驗(yàn)證 string acitonName = actionContext.ActionDescriptor.ActionName; string controllerName = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName; result = new AuthCheckService().CheckRequestFrequency(apikey, $ "api/{controllerName.ToLower()}/{acitonName.ToLower()}" ); } if (result.Code == MResultCodeEnum.successCode) { // 簽名校驗(yàn) // 獲取全部的請(qǐng)求參數(shù) Dictionary< string , string > queryParameters = httpRequest.GetAllQueryParameters(); result = new AuthCheckService().SignCheck(queryParameters, apikey); if (result.Code == MResultCodeEnum.successCode) { // 如果有NoChekokenFilterAttribute 標(biāo)簽 那么直接不做token認(rèn)證 if (actionContext.ActionDescriptor.GetCustomAttributes<XYHAPINoChekokenFilterAttribute>().Any()) { return ; } // 校驗(yàn)token的有效性 // 獲取一個(gè) token string token = httpRequest.Headers.GetValues( "Token" ) == null ? string .Empty : httpRequest.Headers.GetValues( "Token" )[0]; result = new AuthCheckService().CheckToken(token, apikey, httpRequest.FilePath); } } // 輸出 if (result.Code != MResultCodeEnum.successCode) { // 一定要實(shí)例化一個(gè)response,是否最終還是會(huì)執(zhí)行action中的代碼 actionContext.Response = new HttpResponseMessage(HttpStatusCode.OK); //需要自己指定輸出內(nèi)容和類型 HttpContext.Current.Response.ContentType = "text/html;charset=utf-8" ; HttpContext.Current.Response.Write(JsonConvert.SerializeObject(result)); HttpContext.Current.Response.End(); // 此處結(jié)束響應(yīng),就不會(huì)走路由系統(tǒng) } } } |
MVC AuthFilterAttribute實(shí)例代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
/// <summary> /// MVC自定義授權(quán) /// 認(rèn)證授權(quán)有兩個(gè)重寫方法 /// 具體的認(rèn)證邏輯實(shí)現(xiàn):AuthorizeCore 這個(gè)里面寫具體的認(rèn)證邏輯,認(rèn)證成功返回true,反之返回false /// 認(rèn)證失敗處理邏輯:HandleUnauthorizedRequest 前一步返回 false時(shí),就會(huì)執(zhí)行到該方法中 /// 但是,我平時(shí)在應(yīng)用過(guò)程中,一般都是在AuthorizeCore根據(jù)不同的認(rèn)證結(jié)果,直接做認(rèn)證后的邏輯處理 /// </summary> public class XYHMVCAuthorizeAttribute : AuthorizeAttribute { /// <summary> /// 認(rèn)證邏輯 /// </summary> /// <param name="filterContext">過(guò)濾器上下文</param> public override void OnAuthorization(AuthorizationContext filterContext) { // 此處主要寫認(rèn)證授權(quán)的相關(guān)驗(yàn)證邏輯 // 該部分的驗(yàn)證一般包括兩個(gè)部分 // 登錄權(quán)限校驗(yàn) // --我們的一般處理方式是,通過(guò)header中傳遞一個(gè)token來(lái)進(jìn)行邏輯驗(yàn)證 // --當(dāng)然不同的系統(tǒng)在設(shè)計(jì)上也不盡相同,有的也會(huì)采用session等方式來(lái)驗(yàn)證 // --所以最終還是根據(jù)其項(xiàng)目本身的實(shí)際情況來(lái)進(jìn)行對(duì)應(yīng)的邏輯操作 // 具體的頁(yè)面權(quán)限校驗(yàn) // --該部分的驗(yàn)證是具體的到頁(yè)面權(quán)限驗(yàn)證 // --我看有得小伙伴沒(méi)有做到這一個(gè)程度,直接將這一步放在前端js來(lái)驗(yàn)證,這樣不是很安全,但是可以攔住小白用戶 // --當(dāng)然有的系統(tǒng)根本就沒(méi)有做權(quán)限控制,那就更不需要這一個(gè)邏輯了。 // --所以最終還是根據(jù)其項(xiàng)目本身的實(shí)際情況來(lái)進(jìn)行對(duì)應(yīng)的邏輯操作 // 現(xiàn)在用一個(gè)粗暴的方式來(lái)簡(jiǎn)單模擬實(shí)現(xiàn)過(guò),用系統(tǒng)當(dāng)前時(shí)間段秒廚藝3,取余數(shù) // 當(dāng)余數(shù)為0:認(rèn)證授權(quán)通過(guò) // 1:代表為登錄,調(diào)整至登錄頁(yè)面 // 2:代表無(wú)訪問(wèn)權(quán)限,調(diào)整至無(wú)權(quán)限提示頁(yè)面 // 當(dāng)然,在這也還可以做一些IP白名單,IP黑名單驗(yàn)證 請(qǐng)求頻率驗(yàn)證等等 // 說(shuō)到這而,還有一點(diǎn)需要注意,如果我們選擇的是全局注冊(cè)該過(guò)濾器,那么如果有的頁(yè)面根本不需要權(quán)限認(rèn)證,比如登錄頁(yè)面,那么我們可以給不需要權(quán)限的認(rèn)證的控制器或者action添加一個(gè)特殊的注解 AllowAnonymous ,來(lái)排除 // 獲取Request的幾個(gè)關(guān)鍵信息 HttpRequest httpRequest = HttpContext.Current.Request; string acitonName = filterContext.ActionDescriptor.ActionName; string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName; // 注意:如果認(rèn)證不通過(guò),需要設(shè)置filterContext.Result的值,否則還是會(huì)執(zhí)行action中的邏輯 filterContext.Result = null ; int thisSecond = System.DateTime.Now.Second; switch (thisSecond % 3) { case 0: // 認(rèn)證授權(quán)通過(guò) break ; case 1: // 代表為登錄,調(diào)整至登錄頁(yè)面 // 只有設(shè)置了Result才會(huì)終結(jié)操作 filterContext.Result = new RedirectResult( "/html/Login.html" ); break ; case 2: // 代表無(wú)訪問(wèn)權(quán)限,調(diào)整至無(wú)權(quán)限提示頁(yè)面 filterContext.Result = new RedirectResult( "/html/NoAuth.html" ); break ; } } } |
ActionFilter:自定義過(guò)濾器
自定義過(guò)濾器,主要是監(jiān)控action請(qǐng)求前后,處理結(jié)果返回前后的事件。其中API只有請(qǐng)求前后的兩個(gè)方法。
重新方法 |
方法功能描述 |
使用于 |
OnActionExecuting |
一個(gè)請(qǐng)求在進(jìn)入到aciton邏輯前執(zhí)行 |
MVC、API |
OnActionExecuted |
一個(gè)請(qǐng)求aciton邏輯執(zhí)行后執(zhí)行 |
MVC、API |
OnResultExecuting |
對(duì)應(yīng)的view視圖渲染前執(zhí)行 |
MVC |
OnResultExecuted |
對(duì)應(yīng)的view視圖渲染后執(zhí)行 |
MVC |
在這幾個(gè)方法中,我們一般主要用來(lái)記錄交互日志,記錄每一個(gè)步驟的耗時(shí)情況,以便后續(xù)系統(tǒng)優(yōu)化使用。具體的使用,根據(jù)自身的業(yè)務(wù)場(chǎng)景使用。
其中MVC和API的異同點(diǎn),和上面說(shuō)的認(rèn)證授權(quán)的異同類似,不在詳細(xì)說(shuō)明。
下面的一個(gè)實(shí)例代碼:
API定義過(guò)濾器實(shí)例DEMO代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
/// <summary> /// Action過(guò)濾器 /// </summary> public class XYHAPICustomActionFilterAttribute : ActionFilterAttribute { /// <summary> /// Action執(zhí)行開(kāi)始 /// </summary> /// <param name="actionContext"></param> public override void OnActionExecuting(HttpActionContext actionContext) { } /// <summary> /// action執(zhí)行以后 /// </summary> /// <param name="actionContext"></param> public override void OnActionExecuted(HttpActionExecutedContext actionContext) { try { // 構(gòu)建一個(gè)日志數(shù)據(jù)模型 MApiRequestLogs apiRequestLogsM = new MApiRequestLogs(); // API名稱 apiRequestLogsM.API = actionContext.Request.RequestUri.AbsolutePath; // apiKey apiRequestLogsM.API_KEY = HttpContext.Current.Request.QueryString[ "ApiKey" ]; // IP地址 apiRequestLogsM.IP = FilterAttributeHelp.GetIPAddress(actionContext.Request); // 獲取token string token = HttpContext.Current.Request.Headers.GetValues( "Token" ) == null ? string .Empty : HttpContext.Current.Request.Headers.GetValues( "Token" )[0]; apiRequestLogsM.TOKEN = token; // URL apiRequestLogsM.URL = actionContext.Request.RequestUri.AbsoluteUri; // 返回信息 var objectContent = actionContext.Response.Content as ObjectContent; var returnValue = objectContent.Value; apiRequestLogsM.RESPONSE_INFOR = returnValue.ToString(); // 由于數(shù)據(jù)庫(kù)中最大只能存儲(chǔ)4000字符串,所以對(duì)返回值做一個(gè)截取 if (! string .IsNullOrEmpty(apiRequestLogsM.RESPONSE_INFOR) && apiRequestLogsM.RESPONSE_INFOR.Length > 4000) { apiRequestLogsM.RESPONSE_INFOR = apiRequestLogsM.RESPONSE_INFOR.Substring(0, 2000); } // 請(qǐng)求參數(shù) apiRequestLogsM.REQUEST_INFOR = actionContext.Request.RequestUri.Query; // 定義一個(gè)異步委托 ,異步記錄日志 // Func<MApiRequestLogs, string> action = AddApiRequestLogs;//聲明一個(gè)委托 // IAsyncResult ret = action.BeginInvoke(apiRequestLogsM, null, null); } catch (Exception ex) { } } } |
HandleError:錯(cuò)誤處理
異常處理對(duì)于我們來(lái)說(shuō)很常用,很好的利用異常處理,可以很好的避免全篇的try/catch。異常處理箱單很簡(jiǎn)單,值需要自定義集成:ExceptionFilterAttribute,并自定義實(shí)現(xiàn):OnException方法即可。
在OnException我們可以根據(jù)自身需要,做一些相應(yīng)的邏輯處理,比如記錄異常日志,便于后續(xù)問(wèn)題分析跟進(jìn)。
OnException還有一個(gè)很重要的處理,那就是對(duì)異常結(jié)果的統(tǒng)一包裝,返回一個(gè)很友好的結(jié)果給用戶,避免把一些不必要的信息返回給用戶。比如:針對(duì)MVC,那么跟進(jìn)不同異常,統(tǒng)一調(diào)整至友好的提示頁(yè)面等等;針對(duì)API,那么我們可以一個(gè)統(tǒng)一的返回幾個(gè)封裝,便于用戶統(tǒng)一處理結(jié)果。
MVC 的異常處理實(shí)例代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
/// <summary> /// MVC自定義異常處理機(jī)制 /// 說(shuō)道異常處理,其實(shí)我們腦海中的第一反應(yīng),也該是try/cache操作 /// 但是在實(shí)際開(kāi)發(fā)中,很有可能地址錯(cuò)誤根本就進(jìn)入不到try中,又或者沒(méi)有被try處理到異常 /// 該類就發(fā)揮了作用,能夠很好的未經(jīng)捕獲的異常,并做相應(yīng)的邏輯處理 /// 自定義異常機(jī)制,主要集成HandleErrorAttribute 重寫其OnException方法 /// </summary> public class XYHMVCHandleError : HandleErrorAttribute { /// <summary> /// 處理異常 /// </summary> /// <param name="filterContext">異常上下文</param> public override void OnException(ExceptionContext filterContext) { // 我們?cè)谄綍r(shí)的項(xiàng)目中,異常處理一般有兩個(gè)作用 // 1:記錄異常的詳細(xì)日志,便于事后分析日志 // 2:對(duì)異常的統(tǒng)一友好處理,比如根據(jù)異常類型重定向到友好提示頁(yè)面 // 在這里面既能獲取到未經(jīng)處理的異常信息,也能獲取到請(qǐng)求信息 // 在此可以根據(jù)實(shí)際項(xiàng)目需要做相應(yīng)的邏輯處理 // 下面簡(jiǎn)單的列舉了幾個(gè)關(guān)鍵信息獲取方式 // 控制器名稱 注意,這樣獲取出來(lái)的是一個(gè)文件的全路徑 string contropath = filterContext.Controller.ToString(); // 訪問(wèn)目錄的相對(duì)路徑 string filePath = filterContext.HttpContext.Request.FilePath; // url完整地址 string url = (filterContext.HttpContext.Request.Url.AbsoluteUri).ExUrlDeCode(); // 請(qǐng)求方式 post get string httpMethod = filterContext.HttpContext.Request.HttpMethod; // 請(qǐng)求IP地址 string ip = filterContext.HttpContext.Request.GetIPAddress(); // 獲取全部的請(qǐng)求參數(shù) HttpRequest httpRequest = HttpContext.Current.Request; Dictionary< string , string > queryParameters = httpRequest.GetAllQueryParameters(); // 獲取異常對(duì)象 Exception ex = filterContext.Exception; // 異常描述信息 string exMessage = ex.Message; // 異常堆棧信息 string stackTrace = ex.StackTrace; // 根據(jù)實(shí)際情況記錄日志(文本日志、數(shù)據(jù)庫(kù)日志,建議具體步驟采用異步方式來(lái)完成) filterContext.ExceptionHandled = true ; // 模擬根據(jù)不同的做對(duì)應(yīng)的邏輯處理 int statusCode = filterContext.HttpContext.Response.StatusCode; if (statusCode>=400 && statusCode<500) { filterContext.Result = new RedirectResult( "/html/404.html" ); } else { filterContext.Result = new RedirectResult( "/html/500.html" ); } } } |
API 的異常處理實(shí)例代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
/// <summary> /// API自定義異常處理機(jī)制 /// 說(shuō)道異常處理,其實(shí)我們腦海中的第一反應(yīng),也該是try/cache操作 /// 但是在實(shí)際開(kāi)發(fā)中,很有可能地址錯(cuò)誤根本就進(jìn)入不到try中,又或者沒(méi)有被try處理到異常 /// 該類就發(fā)揮了作用,能夠很好的未經(jīng)捕獲的異常,并做相應(yīng)的邏輯處理 /// 自定義異常機(jī)制,主要集成ExceptionFilterAttribute 重寫其OnException方法 /// </summary> public class XYHAPIHandleError : ExceptionFilterAttribute { /// <summary> /// 處理異常 /// </summary> /// <param name="actionExecutedContext">異常上下文</param> public override void OnException(HttpActionExecutedContext actionExecutedContext) { // 我們?cè)谄綍r(shí)的項(xiàng)目中,異常處理一般有兩個(gè)作用 // 1:記錄異常的詳細(xì)日志,便于事后分析日志 // 2:對(duì)異常的統(tǒng)一友好處理,比如根據(jù)異常類型重定向到友好提示頁(yè)面 // 在這里面既能獲取到未經(jīng)處理的異常信息,也能獲取到請(qǐng)求信息 // 在此可以根據(jù)實(shí)際項(xiàng)目需要做相應(yīng)的邏輯處理 // 下面簡(jiǎn)單的列舉了幾個(gè)關(guān)鍵信息獲取方式 // action名稱 string actionName = actionExecutedContext.ActionContext.ActionDescriptor.ActionName; // 控制器名稱 string controllerName =actionExecutedContext.ActionContext.ControllerContext.ControllerDescriptor.ControllerName; // url完整地址 string url = (actionExecutedContext.Request.RequestUri.AbsoluteUri).ExUrlDeCode(); // 請(qǐng)求方式 post get string httpMethod = actionExecutedContext.Request.Method.Method; // 請(qǐng)求IP地址 string ip = actionExecutedContext.Request.GetIPAddress(); // 獲取全部的請(qǐng)求參數(shù) HttpRequest httpRequest = HttpContext.Current.Request; Dictionary< string , string > queryParameters = httpRequest.GetAllQueryParameters(); // 獲取異常對(duì)象 Exception ex = actionExecutedContext.Exception; // 異常描述信息 string exMessage = ex.Message; // 異常堆棧信息 string stackTrace = ex.StackTrace; // 根據(jù)實(shí)際情況記錄日志(文本日志、數(shù)據(jù)庫(kù)日志,建議具體步驟采用異步方式來(lái)完成) // 自己的記錄日志落地邏輯略 ...... // 構(gòu)建統(tǒng)一的內(nèi)部異常處理機(jī)制,相當(dāng)于對(duì)異常做一層統(tǒng)一包裝暴露 MBaseResult< string > result = new MBaseResult< string >() { Code = MResultCodeEnum.systemErrorCode, Message = MResultCodeEnum.systemError }; actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.OK); //需要自己指定輸出內(nèi)容和類型 HttpContext.Current.Response.ContentType = "text/html;charset=utf-8" ; HttpContext.Current.Response.Write(JsonConvert.SerializeObject(result)); HttpContext.Current.Response.End(); // 此處結(jié)束響應(yīng),就不會(huì)走路由系統(tǒng) } } |
總結(jié)
.net過(guò)濾器,我個(gè)人的一句話理解就是:對(duì)action的各個(gè)階段進(jìn)行統(tǒng)一的監(jiān)控處理等操作。.net過(guò)濾器中,其中每一個(gè)種過(guò)濾器的執(zhí)行先后順序?yàn)椋篈uthorize(授權(quán))-->ActionFilter(自定義)-->HandleError(錯(cuò)誤處理)
好了,就先聊到這而,如果什么地方說(shuō)的不對(duì)之處,多多指點(diǎn)和多多包涵。我自己寫了一個(gè)練習(xí)DEMO,里面會(huì)有每一種情況的處理說(shuō)明。有興趣的可以取下載下來(lái)看一看,謝謝。
DEMO在GitHub地址為:https://github.com/xuyuanhong0902/XYH.FilterTest.git
到此這篇關(guān)于聊一聊Asp.net過(guò)濾器Filter那一些事的文章就介紹到這了,更多相關(guān)Asp.net過(guò)濾器Filter內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://www.cnblogs.com/xiaoXuZhi/p/XYH_FilterTest.html