[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 @ 2006-03-07 03:39  dudu  阅读(5883)  评论(7编辑  收藏  举报