转载自: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<stringobject> 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<stringobject> parameters)
{
    ActionExecutingContext preContext = new ActionExecutingContext(controllerContext, actionDescriptor, parameters);
    Func<ActionExecutedContext> seed = () => new ActionExecutedContext(controllerContext, actionDescriptor, falsenull)
    {
        //执行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, truenull)
        {
            Result = preContext.Result
        };
    }
    bool flag = false;
    ActionExecutedContext actionExecutedContext = null;
    try
    {
        //真正的执行action
        actionExecutedContext = continuation();
    }
    catch (ThreadAbortException)
    {
        actionExecutedContext = new ActionExecutedContext(preContext, preContext.ActionDescriptor, falsenull);
        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中断后续请求的更多相关文章

  1. AspNet Core Swagger4.0 生成请求model描述

    今天给大家分享 swagger 俩个冷门的小技巧 获取控制器描述 将 IncludeXmlComments 方法第二个参数设置为 true 即可 public static void IncludeX ...

  2. ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击

    什么是反伪造攻击? 跨站点请求伪造(也称为XSRF或CSRF,发音为see-surf)是对Web托管应用程序的攻击,因为恶意网站可能会影响客户端浏览器和浏览器信任网站之间的交互.这种攻击是完全有可能的 ...

  3. ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击 (转载)

    什么是反伪造攻击? 跨站点请求伪造(也称为XSRF或CSRF,发音为see-surf)是对Web托管应用程序的攻击,因为恶意网站可能会影响客户端浏览器和浏览器信任网站之间的交互.这种攻击是完全有可能的 ...

  4. NET Core 防止跨站请求

    ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击 什么是反伪造攻击? 跨站点请求伪造(也称为XSRF或CSRF,发音为see-surf)是对Web托管应用程序的攻击,因为恶意网站可 ...

  5. AspNet Core 初步认识

    Core 的出现对我我没有很大的影响,当时在Core要发布的时候听到周围的人再聊再谈,我没有去太多关注,就是一个屌丝开发人员. 直到又一次偶然见到一位特别喜欢.net的老开发人员谈起Core时落泪了, ...

  6. AspNet Core Api Restful +Swagger 发布IIS 实现微服务之旅 (二)

    上一步我们创建好CoreApi 接下来在框架中加入 Swagger  并发布  到 IIS (1)首先点击依赖项>管理Nuget包 (2)输入 Swashbuckle.aspnetCore  比 ...

  7. AspNet Core Api Restful +Swagger 实现微服务之旅 (三)

    (1)  访问Rest ful接口时 Token验证  返回数据格式封装 (一)访问时Token验证  返回数据格式封装 1.1访问Api接口 方法 实现         1.1.1 创建访问Rest ...

  8. AspNet Core 下利用普罗米修斯+Grafana构建Metrics和服务器性能的监控 (无心打造文字不喜勿喷谢谢!)

    概述 Prometheus的主要特点 组件 结构图 适用场景 不适用场景 安装node_exporter,系统性能指数收集(收集系统性能情况) 下载文件 解压并复制node_exporter应用程序到 ...

  9. AspNet Core Api Restful +Swagger 发布IIS

    上一步我们创建好CoreApi 接下来在框架中加入 Swagger  并发布  到 IIS (1)首先点击依赖项>管理Nuget包 (2)输入 Swashbuckle.aspnetCore  比 ...

  10. ASP.NET Core 如何记录每次请求的Request信息 - sky 胡萝卜星星 - CSDN博客

    原文:ASP.NET Core 如何记录每次请求的Request信息 - sky 胡萝卜星星 - CSDN博客 版权声明:本文为starfd原创文章,转载请标明出处. https://blog.csd ...

随机推荐

  1. Oracle 的merge into 语法转postgre

    Oracle的merge into 语法 MERGE INTO t1 USING (SELECT id,name FROM t2) t2 ON ( t1.id=t2.id)   //主键 WHEN M ...

  2. go项目,出现too many open files

    刚开始碰到这种异常,以为是代码写的有问题,准备抽时间去改,等有时间正式此问题的时候,发现这种问题一般只会在linux系统上出现,原因如下:linux系统限制了文件打开的最大文件句柄数,系统默认一般是1 ...

  3. c++练习266题:楼层编号

    *266题 原题传送门:http://oj.tfls.net/p/266 题解: #include<bits/stdc++.h>using namespace std; int t;//高 ...

  4. dp-状压dp

    https://www.bilibili.com/video/BV1Z4411x7Kw?from=search&seid=13855865082722302053 状压介绍: 状态表示: 转移 ...

  5. Excel工具(批量生成txt)

    Sub txt() Dim i, j, arr(), brr(), myRow, myCol arr = Sheet1.UsedRange myRow = UBound(arr, 1) myCol = ...

  6. QT debug/moc_frmalarminfo.o:(.data.rel.ro._ZTV12FrmAlarmInfo[_ZTV12FrmAlarmInfo]+0x1c0): undefined reference to `non-virtual thunk to FrmAlarmInfo::~FrmAlarmInfo()'解决方法

    这个报错很具有迷惑性,,,我在网上还看见了ZTI12的报错,但是仔细一看发现是.o文件报错. 简单解释下.o文件(此解释来自百度): o 就是object, 也就相当于windows下编译的obj文件 ...

  7. 广告网络归因技术之SKAdNetwork

    IDFA的背景 为了保护用户隐私,早在2012年就不再允许其生态中的玩家获取用户的唯一标识符,但是商家在移动端打广告的时候又希望能监控到每一次广告投放的效果,因此,苹果想出了折中的办法,就是提供另外一 ...

  8. OnMicro BLE应用方案|蓝牙语音遥控器-OM6621E

    随着物联网技术不断发展,家用电器往智能化方向持续迭代,使用红外遥控器这种传统的互动方式已经满足不了实际的使用需求,蓝牙语音遥控器作为人机交互新载体,逐渐取代传统红外遥控器成为家居设备的标配. 相比于传 ...

  9. Symfony2在Nginx下的配置方法图文教程

    来源: https://www.xp.cn/b.php/79706.html Symfony2在Nginx下的配置方法图文教程 本文详细讲述了Symfony2在Nginx下的配置方法.分享给大家供大家 ...

  10. Jmeter 命令执行脚本并输出报告

    Jmeter 可以通过cmd 命令执行脚本,并输出报告 执行顺序如下: 第一 进入 安装的jmeter bin 目录下:(我安装的是E盘)