[ASP.NET 2.0]PageParser.GetCompiledPageInstance中的一个Bug及解决方法

     最近在将博客园的程序迁移到ASP.NET 2.0,本来在本机虚拟目录中运行时可以正常访问首页,比如:http://localhost/blog。
     可到在服务器上测试时,访问地址:http://test.cnblogs.com,却出现“Object reference not set to an instance of an object”异常,异常产生于 System.Web.UI.PageParser.GetCompiledPageInstance(VirtualPath virtualPath, String inputFile, HttpContext context) 。
     而通过http://test.cnblogs.com/default.aspx却能正常访问,服务器上与本机测试环境主要不同是服务器上程序是运行在IIS根目录,而本机是运行在虚拟目录中。然后,我在本机上将程序放在IIS根目录中运行,出现了同样的问题。
     于是,我用Reflector查看System.Web.UI.PageParser.GetCompiledPageInstance的代码,开始的代码是这样的:       

IHttpHandler handler1; 
 
if (context != null
      

            virtualPath 
= context.Request.BaseDir.Combine(virtualPath); 
      }
 

     由于问题与访问路径有关,所以我格外关注上面的代码,上面的代码是对请求的虚拟路径进行处理。让我们看看context.Request.BaseDir的代码:

internal VirtualPath BaseDir 
    

      
get 
      

            
if (this._baseVirtualDir == null
            

                  
this._baseVirtualDir = this.FilePathObject.Parent; 
            }
 
            
return this._baseVirtualDir; 
      }
 
    }
 

     FilePathObject.Parent是System.Web.VirtualPath的Parent属性,在Parent属性中开始有这样的代码:

if (this.IsRoot)
            
{
                  
return null;
            }

     当以http://localhost/这样的根目录方式访问时,并且在IIS中设置中通配符映射(如果没有设置通配符映射,IIS会自动加上默认文档),这里IsRoot就是true,从IsRoot的代码可以看出:

public bool IsRoot
{
      
get
      
{
            
return (this._virtualPath == "/");
      }

}

       从上面的代码可以看出,当FilePathObject.Parent为null时,context.Request.BaseDir的值就是null,执行GetCompiledPageInstance中的context.Request.BaseDir.Combine(virtualPath); 就会引起“Object reference not set to an instance of an object”异常。 
     我觉得这是一个Bug,因为既然context.Request.BasDir有可能为null,就应该在context.Request.BaseDir.Combine(virtualPath)之前对context.Request.BasDir的值进行检查,对null值情况进行处理,或者在System.Web.VirtualPath的Parent属性中当IsRoot为true是直接返回“/”,而不是null,或者在System.Web.HttpRequest.BasDir中对_baseVirtualDir进行null检查,我觉得还是在HttpRequest中进行处理比较好,因为还有其他地方会调用System.Web.HttpRequest.BasDir,所以更准确地说应该是System.Web.HttpRequest的一个Bug。而在ASP.NET 1.1中就不存在这个bug,因为ASP.NET 1.1中System.Web.HttpRequest.BasDir不会返回null。 
     不知是否有其他方法避免这个问题,继续研究。

,-1,0,93,NULL,0 53353,343460,[ASP.NET 2.0]PageParser.GetCompiledPageInstance中的一个Bug及解决方法,2006-03-05 21:06:00,NULL,1,dudu,duyong@yz2pp.com,218.91.132.198,0,NULL,2006-03-06 23:49:00,NULL,

     最近在将博客园的程序迁移到ASP.NET 2.0,本来在本机虚拟目录中运行时可以正常访问首页,比如:http://localhost/blog。
     可到在服务器上测试时,访问地址:http://test.cnblogs.com,却出现“Object reference not set to an instance of an object”异常,异常产生于 System.Web.UI.PageParser.GetCompiledPageInstance(VirtualPath virtualPath, String inputFile, HttpContext context) 。
     而通过http://test.cnblogs.com/default.aspx却能正常访问,服务器上与本机测试环境主要不同是服务器上程序是运行在IIS根目录,而本机是运行在虚拟目录中。然后,我在本机上将程序放在IIS根目录中运行,出现了同样的问题。
     于是,我用Reflector查看System.Web.UI.PageParser.GetCompiledPageInstance的代码,开始的代码是这样的:       

IHttpHandler handler1; 
 
if (context != null
      

            virtualPath 
= context.Request.BaseDir.Combine(virtualPath); 
      }
 

     由于问题与访问路径有关,所以我格外关注上面的代码,上面的代码是对请求的虚拟路径进行处理。让我们看看context.Request.BaseDir的代码:

internal VirtualPath BaseDir 
    

      
get 
      

            
if (this._baseVirtualDir == null
            

                  
this._baseVirtualDir = this.FilePathObject.Parent; 
            }
 
            
return this._baseVirtualDir; 
      }
 
    }
 

     FilePathObject.Parent是System.Web.VirtualPath的Parent属性,在Parent属性中开始有这样的代码:

if (this.IsRoot)
            
{
                  
return null;
            }

     当以http://localhost/这样的根目录方式访问时,并且在IIS中设置中通配符映射(如果没有设置通配符映射,IIS会自动加上默认文档),这里IsRoot就是true,从IsRoot的代码可以看出:

public bool IsRoot
{
      
get
      
{
            
return (this._virtualPath == "/");
      }

}

       从上面的代码可以看出,当FilePathObject.Parent为null时,context.Request.BaseDir的值就是null,执行GetCompiledPageInstance中的context.Request.BaseDir.Combine(virtualPath); 就会引起“Object reference not set to an instance of an object”异常。 
     我觉得这是一个Bug,因为既然context.Request.BasDir有可能为null,就应该在context.Request.BaseDir.Combine(virtualPath)之前对context.Request.BasDir的值进行检查,对null值情况进行处理,或者在System.Web.VirtualPath的Parent属性中当IsRoot为true是直接返回“/”,而不是null,或者在System.Web.HttpRequest.BasDir中对_baseVirtualDir进行null检查,我觉得还是在HttpRequest中进行处理比较好,因为还有其他地方会调用System.Web.HttpRequest.BasDir,所以更准确地说应该是System.Web.HttpRequest的一个Bug。而在ASP.NET 1.1中就不存在这个bug,因为ASP.NET 1.1中System.Web.HttpRequest.BasDir不会返回null。 
     不知是否有其他方法避免这个问题,继续研究。 
     [2006年3月6日修改]已经找到一种解决方法:在PageParser.GetCompiledPageInstance之前进行RewritePath处理,示例代码如下:

if (url.ToLower().IndexOf(".aspx"< 0)
           {
               
if (!url.EndsWith("/"))
               {
                   url 
+= "/";
               }
               url 
+= "default.aspx" ;
               context.RewritePath(url);
               
return PageParser.GetCompiledPageInstance(url, pagepath, context);
           }

posted on 2006-03-07 03:39 dudu 阅读(3891) 评论(6)  编辑 收藏 网摘 所属分类: ASP.NET

评论

#1楼 2006-03-07 17:36 韦恩卑鄙      

1.1升级到2.0好多工程会变得不伦不类需要手动改5555 加油啊   回复  引用  查看    

#2楼[楼主] 2006-03-07 23:06 dudu      

@韦恩卑鄙
你可以参考这篇文章中的方法: http://dudu.cnblogs.com/archive/2006/02/18/333115.html">http://dudu.cnblogs.com/archive/2006/02/18/333115.html
  回复  引用  查看    

#3楼 2006-03-10 19:07 Activer[未注册用户]

如果说 ASP.NET 1.1可以用的,ASP.NET 2.0 不能用,这个叫做不兼容,应该算不上Bug

如果要说到PageParser.GetCompiledPageInstance,微软本来就是说不要用这个东西,你偏偏要用,如果说喜欢自己搞编译控制,在.NET 1.1里面用用PageParser.GetCompiledPageInstance就可以了,为什么还要到.NET 2.0里面用?

“当以http://localhost/这样的根目录方式访问时,并且在IIS中设置中通配符映射(如果没有设置通配符映射,IIS会自动加上默认文档),”

如果没有设置通配符映射,是IIS在做这个控制,现在你设置了通配符映射,你却不去做这样的控制,却说.NET 不给你做好。.NET真是怨,你要控制 就给你控制了,给你控制 你却不去控制,却说.NET没有控制好
  回复  引用    

#4楼[楼主] 2006-03-10 21:56 dudu      

@Activer
请看 http://www.cnblogs.com/dudu/archive/2006/03/10/345107.html#347493">http://www.cnblogs.com/dudu/archive/2006/03/10/345107.html#347493 中的回复。
  回复  引用  查看    

#5楼 2007-12-31 16:42 武眉博<活靶子.Net>      

手工Ping一下:
http://www.cnblogs.com/huobazi/archive/2007/12/31/UrlRewriteAndHttpHanderAndMakeStaticHtmlFiles.html">http://www.cnblogs.com/huobazi/archive/2007/12/31/UrlRewriteAndHttpHanderAndMakeStaticHtmlFiles.html

  回复  引用  查看    

#6楼 2008-03-10 22:52 gzjl[未注册用户]

为何我按照你的解决方法在PageParser.GetCompiledPageInstance之前进行RewritePath处理,根目录中运行没有问题了,但是点任何一个随笔均出现"the entry could not be found or has been removed"   回复  引用    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 344351




历史上的今天:
2005-03-07 [新功能]总是只列出标题

相关文章:

相关链接:

导航

公告

人生的真正价值在于从何种程度与何种意义上摆脱自我!
明天继续更新评论功能
<2006年3月>
2627281234
567891011
12131415161718
19202122232425
2627282930311
2345678

统计

与我联系

搜索

 

常用链接

留言簿

随笔分类

随笔档案

新闻分类

相册

HJ

朋友的博客

网站收藏

小组

友情链接

最新随笔

最新评论

阅读排行榜

评论排行榜

60天内阅读排行