破碎了无痕

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

最近写一个login用的handler,发现了一个以往没太注意的问题:

        public void ProcessRequest(HttpContext context)
        {
            
try
            {
                
// Identity authentication
                if (!AuthenticateIdentity(context))
                {
                   context.Response.Redirect(Page1);
                }

                
// Check parameters
                if (!TryCheckParams(context))
                {
                   context.Response.Redirect(Page2);
                }

                
// Valid login
                   context.Response.Redirect(Page3);
            }
            
catch (Exception ex)
            {
                DoSth();
                context.Response.Redirect(Page4);
            }

        }

     如上,我们常希望满足不同的条件就redirect到不同的page去,以上代码运行起来似乎没什么问题,页面能够正常跳转,但仔细检查error log会发现有很多异常抛出:ThreadAbortException (0): [mscorlib] Thread was being aborted.

     原因就在于Response.Redirect 内部调用了Response.End,而Response.End 方法停止页面的执行,并将该执行变换到应用程序的事件管线中的 Application_EndRequest 事件。 Response.End 后面的代码行将不执行。

     网上提供有解决方案是调用Response.Redirect的重载方法Redirect(string url, bool endResponse)并传入false,阻止对Response.End的调用。但在本实例中,这种方法也不能解决问题,因为我方法里面的逻辑判断是线性的if...if...if...,这就导致Response.Redirect可能被执行多次从而产生异常。要避免此错误,可以使用嵌套语句if...else if...else...,这样可以避免重复执行Redirect,但对于复杂的逻辑,这个嵌套会很复杂,非常不易于阅读。那么怎么办呢?我后来想到整个方法只在最后做Rediret跳转,而在前面所有的条件分支中只设置redirectURL,然后用goto语句强行转移到最后面的跳转语句。这样问题确实解决了,但目前很多公司都不建议使用goto语句,认为它会造成程序逻辑的混乱,不易于阅读和维护。

     其实最佳方案是将以上代码提取到一个单独的方法HandleRequest(),这个方法执行所有的逻辑并返回最终的redirectURL,而ProcessRequest方法调用HandleRequest获取redirectURL并执行跳转即可。

参考:http://www.cnblogs.com/rolinson/archive/2005/01/22/95710.html

posted on 2011-02-22 15:18  破碎了无痕  阅读(1854)  评论(0编辑  收藏  举报