ASPNET Core ActionFilterAttribute中断后续请求
转载自:https://www.cnblogs.com/luconsole/p/4346669.html
SPNET MVC如何正确的中断请求?
感觉是这样?
在aspnet开发过程中如果想要中断当前的http处理,以前在aspnet中一直是Response.End();
在这Response.End()之后的当前请求应有的代码都不会执行了,
但是在aspnetmvc中,就算调用Response.End();还是会执行!!
1
2
3
4
5
6
7
8
9
10
11
12
|
//aspnet webform if (ok) Response.End(); //save不会继续执行 Save(); //aspnet mvc if (ok) Response.End(); //save会继续执行 Save(); |
aspnetmvc action 如何简单处理?
如果你在action中的逻辑需要中断,你可以变通的通过逻辑判断来中断,
比如:
if(ok)
{
//应有的逻辑
}
else
{
//中断
} //或者 if(!ok)
return Content("NO");
但是如果是在过滤器中!
1
2
3
4
5
6
|
protected virtual void OnActionExecuted(ActionExecutedContext filterContext); protected virtual void OnActionExecuting(ActionExecutingContext filterContext); protected virtual void OnAuthorization(AuthorizationContext filterContext); protected virtual void OnException(ExceptionContext filterContext); protected virtual void OnResultExecuted(ResultExecutedContext filterContext); protected virtual void OnResultExecuting(ResultExecutingContext filterContext); |
你的 逻辑判断 和 Response.End(); 都是无效的!
看到很多人都是用的跳转!如果是aspnet mvc web api,往哪里跳转呢。
正确的aspnet mvc filter Cancel Execution姿势!
那就是赋值 filterContext.Result!
例如OnActionExecuting
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
var headerAuth = filterContext.HttpContext.Request.Headers["_applogin_"];
if (string.IsNullOrEmpty(headerAuth))
{
filterContext.Result = new ContentResult()
{
Content = "{code:9999,message:'no login'}",
ContentEncoding = Encoding.UTF8
};
} base.OnActionExecuting(filterContext);
}
}
为什么赋值了Context.Result就不会继续执行后面的过滤器和action的代码?
先看下aspnetmvc源码!
aspnet mvc 源码:ControllerActionInvoker.cs
附上简单注释:
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
/// <summary> /// 执行一个 控制器方法 /// </summary> /// <param name="controllerContext"></param> /// <param name="actionName"></param> /// <returns></returns> public virtual bool InvokeAction(ControllerContext controllerContext, string actionName) { if (controllerContext == null ) { throw new ArgumentNullException( "controllerContext" ); } if ( string .IsNullOrEmpty(actionName)) { throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName" ); } //根据请求获取控制信息 ControllerDescriptor controllerDescriptor = this .GetControllerDescriptor(controllerContext); //根据请求和控制器获取action信息 ActionDescriptor actionDescriptor = this .FindAction(controllerContext, controllerDescriptor, actionName); //action不为空 if (actionDescriptor != null ) { //获取或滤器信息 FilterInfo filters = this .GetFilters(controllerContext, actionDescriptor); try { //获取aspnetmvc自带的Authorization信息 AuthorizationContext authorizationContext = this .InvokeAuthorizationFilters(controllerContext, filters.AuthorizationFilters, actionDescriptor); //这里我们可以看到,在授权的代码里面也可以赋值,当在获取授权时赋值了Result,当前执行会被返回Result,action的代码和过滤器的代码将不会执行 if (authorizationContext.Result != null ) { this .InvokeActionResult(controllerContext, authorizationContext.Result); } else { //判断请求数据验证 if (controllerContext.Controller.ValidateRequest) { ControllerActionInvoker.ValidateRequest(controllerContext); } //获取请求参数 IDictionary< string , object > parameterValues = this .GetParameterValues(controllerContext, actionDescriptor); //获取执行上下文 ActionExecutedContext actionExecutedContext = this .InvokeActionMethodWithFilters(controllerContext, filters.ActionFilters, actionDescriptor, parameterValues); //开始执行过滤器和action this .InvokeActionResultWithFilters(controllerContext, filters.ResultFilters, actionExecutedContext.Result); } } catch (ThreadAbortException) { throw ; } catch (Exception exception) { ExceptionContext exceptionContext = this .InvokeExceptionFilters(controllerContext, filters.ExceptionFilters, exception); if (!exceptionContext.ExceptionHandled) { throw ; } this .InvokeActionResult(controllerContext, exceptionContext.Result); } return true ; } return false ; } //执行过滤器和action // System.Web.Mvc.ControllerActionInvoker protected virtual ActionExecutedContext InvokeActionMethodWithFilters(ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary< string , object > parameters) { ActionExecutingContext preContext = new ActionExecutingContext(controllerContext, actionDescriptor, parameters); Func<ActionExecutedContext> seed = () => new ActionExecutedContext(controllerContext, actionDescriptor, false , null ) { //执行action Result = this .InvokeActionMethod(controllerContext, actionDescriptor, parameters) }; //反序filters,以active执行的seed为基础,累加计算filters得到一个 ActionExecutedContext //这里面就是重点了,大概的意思是先执行所有过滤器,最后执行active,如果中途过滤器产生了Context.Result,则不会继续执行后面的过滤器和active, Func<ActionExecutedContext> func = filters.Reverse<IActionFilter>() .Aggregate(seed, (Func<ActionExecutedContext> next, IActionFilter filter) => () => ControllerActionInvoker.InvokeActionMethodFilter(filter, preContext, next)); return func(); } // System.Web.Mvc.ControllerActionInvoker internal static ActionExecutedContext InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func<ActionExecutedContext> continuation) { //调用OnActionExecuting filter.OnActionExecuting(preContext); if (preContext.Result != null ) { return new ActionExecutedContext(preContext, preContext.ActionDescriptor, true , null ) { Result = preContext.Result }; } bool flag = false ; ActionExecutedContext actionExecutedContext = null ; try { //真正的执行action actionExecutedContext = continuation(); } catch (ThreadAbortException) { actionExecutedContext = new ActionExecutedContext(preContext, preContext.ActionDescriptor, false , null ); filter.OnActionExecuted(actionExecutedContext); throw ; } catch (Exception exception) { flag = true ; actionExecutedContext = new ActionExecutedContext(preContext, preContext.ActionDescriptor, false , exception); filter.OnActionExecuted(actionExecutedContext); if (!actionExecutedContext.ExceptionHandled) { throw ; } } if (!flag) { filter.OnActionExecuted(actionExecutedContext); } return actionExecutedContext; } |
从以上代码我们可以看出,一个action的执行流程是这样的:
1>根据请求获取Controller和action的信息
2>获取应该有的过滤器
3>Authorization验证,如果不通过则返回
4>ValidateRequest,验证请求数据
5>执行过滤器和active,如果在中途过滤器产生Result,则后面的过滤器和active将不会执行!
所以,最正确的方法就是在过滤器中赋值Result!
ASPNET Core ActionFilterAttribute中断后续请求的更多相关文章
- AspNet Core Swagger4.0 生成请求model描述
今天给大家分享 swagger 俩个冷门的小技巧 获取控制器描述 将 IncludeXmlComments 方法第二个参数设置为 true 即可 public static void IncludeX ...
- ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击
什么是反伪造攻击? 跨站点请求伪造(也称为XSRF或CSRF,发音为see-surf)是对Web托管应用程序的攻击,因为恶意网站可能会影响客户端浏览器和浏览器信任网站之间的交互.这种攻击是完全有可能的 ...
- ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击 (转载)
什么是反伪造攻击? 跨站点请求伪造(也称为XSRF或CSRF,发音为see-surf)是对Web托管应用程序的攻击,因为恶意网站可能会影响客户端浏览器和浏览器信任网站之间的交互.这种攻击是完全有可能的 ...
- NET Core 防止跨站请求
ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击 什么是反伪造攻击? 跨站点请求伪造(也称为XSRF或CSRF,发音为see-surf)是对Web托管应用程序的攻击,因为恶意网站可 ...
- AspNet Core 初步认识
Core 的出现对我我没有很大的影响,当时在Core要发布的时候听到周围的人再聊再谈,我没有去太多关注,就是一个屌丝开发人员. 直到又一次偶然见到一位特别喜欢.net的老开发人员谈起Core时落泪了, ...
- AspNet Core Api Restful +Swagger 发布IIS 实现微服务之旅 (二)
上一步我们创建好CoreApi 接下来在框架中加入 Swagger 并发布 到 IIS (1)首先点击依赖项>管理Nuget包 (2)输入 Swashbuckle.aspnetCore 比 ...
- AspNet Core Api Restful +Swagger 实现微服务之旅 (三)
(1) 访问Rest ful接口时 Token验证 返回数据格式封装 (一)访问时Token验证 返回数据格式封装 1.1访问Api接口 方法 实现 1.1.1 创建访问Rest ...
- AspNet Core 下利用普罗米修斯+Grafana构建Metrics和服务器性能的监控 (无心打造文字不喜勿喷谢谢!)
概述 Prometheus的主要特点 组件 结构图 适用场景 不适用场景 安装node_exporter,系统性能指数收集(收集系统性能情况) 下载文件 解压并复制node_exporter应用程序到 ...
- AspNet Core Api Restful +Swagger 发布IIS
上一步我们创建好CoreApi 接下来在框架中加入 Swagger 并发布 到 IIS (1)首先点击依赖项>管理Nuget包 (2)输入 Swashbuckle.aspnetCore 比 ...
- ASP.NET Core 如何记录每次请求的Request信息 - sky 胡萝卜星星 - CSDN博客
原文:ASP.NET Core 如何记录每次请求的Request信息 - sky 胡萝卜星星 - CSDN博客 版权声明:本文为starfd原创文章,转载请标明出处. https://blog.csd ...
随机推荐
- MyBatis-Plus的批量处理之insertBatchSomeColumn
一.MyBatis插入数据方式 1. MyBatis单条save方式: 2. MyBatis多条mapper.xml里写foreach循环: 3. MyBatis-Plus多条saveBatch方式, ...
- CentOS7.6下安装MySql和Redis
安装的MySQL为5.7版本1.下载安装官方的Yum Repository [root@localhost ~]# wget http://dev.mysql.com/get/mysql57-comm ...
- linux挂载磁盘步骤
一.查看需要挂载设备,如下sda(默认路径/dev/sda) 二.新建分区,执行如下命令进入操作 fdisk /dev/sda 1.m 查看可操作的命令 2.键入 n ,根据需要新建分区 3.键入 d ...
- oracle的dblink创建连接查询及使用
https://www.cnblogs.com/muhai/p/15527463.html https://www.cnblogs.com/leipei2352/archive/2011/04/21/ ...
- idea中怎么查找替换数据?
快捷键全局查询所有:crtl+shift+F 快捷键全局替换所有:crtl+shift+R 1.crtl+f crtl+r 快捷键全局查询所有:crtl+shift+F 快捷键全局替换所有:crtl+ ...
- vue3 门户网站搭建5-图标
奈何 element 自带的图标太少,不够用,故打算使用 vite-plugin-svg-icons 组件来封装 svg-icon . ps: ui 框架选用的 element-ui,为了能跟 vue ...
- DSP(数字信号处理)与监控摄像机相关技术解读
提起安防领域,我们第一个想到的应该就是监控摄像机了,它对于安防的重要性,就像人的眼睛对于人的作用一样,是重要的信息获取来源. 监控摄像机广泛应用于学校.公司.银行.交通.平安城市等多个安保领域. 广州 ...
- Vue源码中的数据代理
直接开讲: 由于这个Vue底层封装的函数太多了,我这里只讲思路不说具体的执行了什么函数. const vm=new Vue({这里写一个data,可以是对象也可以是函数}) 在写这段代码的时候 ...
- this指向问题大全和call,apply,bind详解
详细笔记链接:https://www.jianshu.com/p/bc541afad6ee 函数内外作用域问题: var a = 1function f1(){ var a = 2 console.l ...
- 13-之容器资源需求、资源限制及Metric-server(Heapster)
目录 容器资源需求.资源限制及Heapster Heapster 资源指标API及自定义指标API k8s-promtheus监控部署 node-exporter prometheus kube-st ...