zoukankan      html  css  js  c++  java
  • 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页面显示:

    image

    调试信息输出:

    QQ图片20130715162800

    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页面输出:

    image

    调试信息:

    image

    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的私有变量。

    image

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

    普通异常的弹出窗口:

    image

    调试信息输出:

    image

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

    image

    是由于ThreadAbortException是SystemException(系统异常)被特殊对待了吗?

    这只是一个衍生出来的疑问,继续刚才的问题,用ThreadAbortException和ASP.NET MVC作为关键字去google搜索,在Will保哥的博客中得到了解答!

    具体可以参见这篇博客下的评论和另一篇博客

    image

    经过保哥的指点,通过Reflector去查看源码,证实了是_timeoutState的作用。

    HttpResponse.End中代码:

    image

    IsInCancellablePeriod属性:

    image

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

    image

  • 相关阅读:
    ES6新特性
    ng-bind与ng-medol 区别
    验证输入两次密码是否一致angularjs
    最全的node.js安装步骤
    JAVA基础
    localStorage 个人使用总结
    mac中怎么安装python3
    macbook配置homebrew以及安装python3
    python之函数进阶
    mysql数据库入门
  • 原文地址:https://www.cnblogs.com/v5wa/p/3165367.html
Copyright © 2011-2022 走看看