日期:2014-05-17  浏览次数:20960 次

asp.net mvc RouteCollection的RouteExistingFiles属性理解

RouteCollectiond的RouteExistingFiles属性一看这个名字,我想大家就能猜出来它的意思,对静态资源是否启用路由。我在Asp.net Web.config文件读取路径你真的清楚吗?里面做demo时遇到这样一个问题:

项目结构如下:

我原本是用来让程序读views/channel/men/web.config文件,当我添加了men文件夹后,整过路由都出错了。

我的路由代码:

  routes.MapRoute("channelDefault", "{ChannelName}/{action}", new
            {
                controller = "Channel",
                action = "Default"
            });

controller代码:

public ActionResult Default()
        {
            string channelName = RouteData.Values["ChannelName"].ToString().Trim();
            string actionName = RouteData.Values["action"].ToString().Trim();
            string viewName = string.Format("{0}/{1}", channelName, actionName);
            return View(viewName);
        }

整个代码是不是都很简单啊。当我添加了men文件夹后路由出错,移除men路由就对了。那么问题也就找到了       routes.RouteExistingFiles = true;我对RouteExistingFiles树立的理解是:对已存在文件是否启用路由,其实这个理解有点不对啊

让我们来看看RouteCollection的GetRouteData方法,里面有这么一段:

 if (!this.RouteExistingFiles)
        {
            string appRelativeCurrentExecutionFilePath = httpContext.Request.AppRelativeCurrentExecutionFilePath;
            if (((appRelativeCurrentExecutionFilePath != "~/") && (this._vpp != null)) && (this._vpp.FileExists(appRelativeCurrentExecutionFilePath) || this._vpp.DirectoryExists(appRelativeCurrentExecutionFilePath)))
            {
                return null;
            }
        }
        using (this.GetReadLock())
        {
            foreach (RouteBase base2 in this)
            {
                RouteData routeData = base2.GetRouteData(httpContext);
                if (routeData != null)
                {
                    return routeData;
                }
            }
        }

它检查文件和文件目录是否存在。例如我的请求路径是http://localhost:11286/men,那么httpContext.Request.AppRelativeCurrentExecutionFilePath的取值是~/men/,而men这个路径树存在的。所以及返回null了。我们知道在UrlRoutingModule的PostResolveRequestCache方法中会调用this.RouteCollection.GetRouteData(context)获取RouteData,如果返回值不为null才会调用context.RemapHandler(httpHandler),那么如果这里返回为null也就表示路由失败,那么也就找不到对应的handler来处理此次请求了。

现在让我们来看看你HostingEnvironment.VirtualPathProvider是如果查找文件和路径的,首先我们要知道HostingEnvironment.VirtualPathProvider其实是一个MapPathBasedVirtualPathProvider实例

public override bool DirectoryExists(string virtualDir)
{
    return this.CacheLookupOrInsert(virtualDir, false);
}
public override bool FileExists(string virtualPath)
{
    return this.CacheLookupOrInsert(virtualPath, true);
}
从DirectoryExists和FileExists方法来看,它主要是调用了一个CacheLookupOrInsert方法。
 private bool CacheLookupOrInsert(string virtualPath, bool isFile)
    {
        string physicalPath = HostingEnvironment.MapPathInternal(virtualPath);
        bool doNotCacheUrlMetadata = CachedPathData.DoNotCacheUrlMetadata;
        string key = null;
        if (!doNotCacheUrlMetadata)
        {
            key = this.CreateCacheKey(isFile, physicalPat