Response.End()在Webform和ASP.NET MVC下的表现差异
前几天在博问中看到一个问题——Response.End()后,是否停止执行?MVC与WebForm不一致。看到LZ的描述后,虽然奇怪于为何用Response.End()而不用return方式去控制流程,但基于自己以往的认识,还是回答了说需要return。
因为以往的开发过程中,虽然没有用过Response.End()的方式像LZ所说地那样“方便地从多层调用中退出”,但是始终是认为Response.End()是不能终止其后代码执行的,思维路线大概是:Response.End()只是结束了HTTP返回流的写入,但是代码依然没有return啊,例如Page_Load中使用了Response.End(),但是这个方法并没有被跳出/终止。
之后LZ编辑了问题,继续提到了问题没有解决,又附带了伪代码希望大家帮忙改进书写方式。直到此时,由于自己的思维惯性,我依然我没有去写DEMO去验证对比webform和mvc下的Response.End(),简单地用主动throw new Exception的方式写出了MVC下“好看一点”的代码。
之后在回复中,LZ再次重复了Response.End()确实在webform和mvc中存在差异,我抱着试一试地心态测了一个疗程。真的有点吃惊,Reponse.End()在webfrom和ASP.NET MVC下的表现确实是不同的!
ASP.NET MVC代码:
public ActionResult Index()
{
Method0();
Method1();
Method2();
Response.Write("All methods success.");
return View("I don't think so.");
} private void Method0()
{
Debug.WriteLine("Method 0 process...");
bool flag = true;
if (!flag)
{
Response.Write("Method 0 failure.");
Response.End();
}
} private void Method1()
{
Debug.WriteLine("Method 1 process...");
bool flag = false;
if (!flag)
{
Response.Write("Method 1 failure.");
Response.End();
}
} private void Method2()
{
Debug.WriteLine("Method 2 process...");
bool flag = false;
if (!flag)
{
Response.Write("Method 2 failure.");
Response.End();
}
}
web页面显示:

调试信息输出:

Response.End()后的代码继续执行,这与之前的认识是没有出入的,接下来看webform。
Webform代码:
protected void Page_Load(object sender, EventArgs e)
{
Method0();
Method1();
Method2();
Response.Write("All methods success.");
} private void Method0()
{
Debug.WriteLine("Method 0 process...");
bool flag = true;
if (!flag)
{
HttpContext.Current.Response.Write("Method 0 failure.");
System.Web.HttpContext.Current.Response.End();
}
} private void Method1()
{
Debug.WriteLine("Method 1 process...");
bool flag = false;
if (!flag)
{
HttpContext.Current.Response.Write("Method 1 failure.");
System.Web.HttpContext.Current.Response.End();
}
} private void Method2()
{
Debug.WriteLine("Method 2 process...");
bool flag = true;
if (!flag)
{
HttpContext.Current.Response.Write("Method 2 failure.");
System.Web.HttpContext.Current.Response.End();
}
}
web页面输出:

调试信息:

web页面的输出一致,调试窗口那里可是大不一样。webform并未接着执行Response.End()后的代码,因为抛出了一个ThreadAbortException异常。这时候,我首先想到的是ASP.NET MVC下的Response对象类型是否和ASP.NET不同,导致他们的处理方式不同。
后来发现虽然ASP.NET MVC中的Response类型是HttpResponseBase,但是显式地去调用System.Web.Context.Current.Response.End()结果依旧。通过Reflector查看ASP.NET MVC下HttpResponseBase的实现类HttpResponseWrapper,End方法的实现如图,this_httpResponse是HttpResponse的私有变量。

查到这儿思路一度中断,只好回头去对比调试信息中的表现,从ThreadAbortException这个异常入手,发现在ASP.NET MVC中先调用Response.End(),再调用Thread.CurrentThread.Abort()可以达到webform下调用Response.End()的效果。当然其他异常也能模拟,但是此时发现了一个小问题,就是抛出普通异常的时候和抛出ThreadAbortException异常略有不同。
普通异常的弹出窗口:

调试信息输出:

ThreadAbortException异常没有弹出那个窗口,调试信息中也多了一条信息。

是由于ThreadAbortException是SystemException(系统异常)被特殊对待了吗?
这只是一个衍生出来的疑问,继续刚才的问题,用ThreadAbortException和ASP.NET MVC作为关键字去google搜索,在Will保哥的博客中得到了解答!

经过保哥的指点,通过Reflector去查看源码,证实了是_timeoutState的作用。
HttpResponse.End中代码:

IsInCancellablePeriod属性:

问题得到了解决!~但是我还有一个小疑问,也就是从Reflector中看到End方法的源码,IsInCancellablePeriod是bool类型,但是却判断是否等于null。这怎么也是不合适的吧,是Reflector的解析错误还是其他原因导致的呢?

Response.End()在Webform和ASP.NET MVC下的表现差异的更多相关文章
- C# 发送邮件整理,包括控制台程序、WPF、WebForm 及 ASP.NET MVC
一直想把发送邮件的功能掌握,总是各种情况拖着了,这两天终于看了一下,整理一下,希望能帮到想学的. 发送邮件使用SMTP服务器,有两种方案,一种是使用IIS的SMTP功能:另一种是直接使用邮件供应商的S ...
- WebForm和Asp.Net MVC的理解
我对WebForm和Asp.Net MVC的理解 比较WebForm和Mvc的请求处理方式 首先简单了解一下Asp.Net中怎么对页面进行请求处理的: 在管道的第7-8个事件之间,有一个MapHt ...
- 性能差异 ASP.NET WebForm与ASP.NET MVC
一.为什么说 ASP.NET WebForm 比 ASP.NET MVC 要差? WebForm 顾名思义,微软一向主打简单化,窗体模式,拖拽控件就能做网站了, 然而这也引发了许多 Java 和 .N ...
- ASP.NET MVC下使用AngularJs语言(五):ng-selected
这次学习ng-selected语法,这个是为DropDownList下拉列表显示默认选项. 演示从下面步骤开始 1,新建一个model: 上面#14行代码的property,数据类型为bool.即是存 ...
- ASP.NET mvc下在Controller下action的跳转方式
在ASP.NET mvc下,action有多种挑战方式: return RedirectToAction("Index");//一个参数时在本Controller下 如果Redir ...
- ASP.NET MVC 下使用支付宝支付接口 以及 ASP.NET Core 下相关改造支付
通过nuget首先引用AopSdk.dll 包 下面写的是 Asp.Net MVC 下相关的支付接口 APP支付 配置客户端相关的参数,配置成自己的代码就可以了 private string APPI ...
- ASP.NET MVC下的四种验证编程方式[续篇]
在<ASP.NET MVC下的四种验证编程方式>一文中我们介绍了ASP.NET MVC支持的四种服务端验证的编程方式("手工验证"."标注Validation ...
- ASP.NET MVC下的四种验证编程方式
ASP.NET MVC采用Model绑定为目标Action生成了相应的参数列表,但是在真正执行目标Action方法之前,还需要对绑定的参数实施验证以确保其有效性,我们将针对参数的验证成为Model绑定 ...
- ASP.NET MVC下的四种验证编程方式[续篇]【转】
在<ASP.NET MVC下的四种验证编程方式> 一文中我们介绍了ASP.NET MVC支持的四种服务端验证的编程方式(“手工验证”.“标注ValidationAttribute特性”.“ ...
随机推荐
- ThinkPHP 3.2.3 多模块 和 多应用 的配置
多模块 在 ThinkPHP 3.2.3 中,默认的应用目录是 ./Application,下面的默认模块是 Home 模块,如果此时需要添加一个 Admin 模块用于后台应用,根据手册 http:/ ...
- 为什么Visual Studio的安装目录下有名为1033或2052的文件夹?
一直不清楚MS诸多产品的安装目录下为什么总有个名为1033或者2052的目录 搜索一下才知道,原来叫 LCID(Locale ID,区域性标识符) 常见的如:1033表示英语(美国),2052表示中文 ...
- Postgre cannot insert multiple commands into a prepared statement
悲剧... FireDAC连接Postgre数据库, 使用默认的属性, 一次执行多条SQL的时候, 会报"cannot insert multiple commands into a pre ...
- 服务器IP地址后修改SQL Server配置
1. 修改TCP/IP 属性的IP 地址 修改该实例的协议.修改TCP/IP协议的属性,将IP地址更新为当前的最新IP 地址.然后重启该实例. 2.查看全部侦听再检查SQL Server 实例的TCP ...
- 移动端开发tips
为什么使用touch click有300sm的延迟 touch支持多点触摸 手势操作
- Spring中bean的scope详解
如何使用spring的作用域: <bean id="role" class="spring.chapter2.maryGame.Role" scope=& ...
- PHP 教程
PHP 教程 源地址 PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言. PHP 是免费的,并且使用非常广泛.同时,对于像微软 ASP 这样的竞争者来说,PHP 无疑是另一种高效率的选项. ...
- 导出db2数据库的表结构和数据(转载)
对于db2数据库,导入和导出表结构和数据其实很简单,只需要用到db2look和db2move两个命令即可.这两个命令都需要在客户端的命令行处理器 中执行,但对于数据库服务器和客户端不在同一机器上的 ...
- JAVA TcpServer端使用Scanner读取不到数据的解决办法
在使用JAVA进行Socket通信时,在Server端使用Scanner的nextLine()方法读取数据时,一直读取不到数据是因为Scanner是一个扫描器,它扫描数据都是去内存中一块缓冲区中进行扫 ...
- 一个注解方式webSocket demo
前段时间在研究websocket.其中遇到了一些bug.这里跟大家分享这过程. 首先介绍一下websocket WebSocket是HTML5的一种新协议,实现了浏览器和服务器的双全工通信,能更好的节 ...