前几天在博问中看到一个问题——Response.End()后,是否中止执行?MVC与WebForm不一致。看到LZ的描述后,虽然奇怪于为什么用Response.End()而不用return方式去控制流程,但基于本身以往的认识,仍是回答了说须要return。web
由于以往的开发过程当中,虽然没有用过Response.End()的方式像LZ所说地那样“方便地从多层调用中退出”,可是始终是认为Response.End()是不能终止其后代码执行的,思惟路线大概是:Response.End()只是结束了HTTP返回流的写入,可是代码依然没有return啊,例如Page_Load中使用了Response.End(),可是这个方法并无被跳出/终止。mvc
以后LZ编辑了问题,继续提到了问题没有解决,又附带了伪代码但愿你们帮忙改进书写方式。直到此时,因为本身的思惟惯性,我依然我没有去写DEMO去验证对比webform和mvc下的Response.End(),简单地用主动throw new Exception的方式写出了MVC下“好看一点”的代码。app
以后在回复中,LZ再次重复了Response.End()确实在webform和mvc中存在差别,我抱着试一试地心态测了一个疗程。真的有点吃惊,Reponse.End()在webfrom和ASP.NET MVC下的表现确实是不一样的!post
ASP.NET MVC代码:this
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页面显示:google
调试信息输出:spa
Response.End()后的代码继续执行,这与以前的认识是没有出入的,接下来看webform。3d
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页面输出:code
调试信息:
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的解析错误仍是其余缘由致使的呢?