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, physicalPath);
            bool? nullable = HttpRuntime.CacheInternal[key] as bool?;
            if (nullable.HasValue)
            {
                return nullable.Value;
            }
        }
        bool flag2 = isFile ? File.Exists(physicalPath) : Directory.Exists(physicalPath);
        if (!doNotCacheUrlMetadata)
        {
            CacheDependency dependencies = null;
            string filename = flag2 ? physicalPath : FileUtil.GetFirstExistingDirectory(AppRoot, physicalPath);
            if (filename != null)
            {
                dependencies = new CacheDependency(filename);
                TimeSpan urlMetadataSlidingExpiration = CachedPathData.UrlMetadataSlidingExpiration;
                HttpRuntime.CacheInternal.UtcInsert(key, flag2, dependencies, Cache.NoAbsoluteExpiration, urlMetadataSlidingExpiration);
            }
        }
        return flag2;
    }

 

這里其中有string physicalPath = HostingEnvironment.MapPathInternal(virtualPath);這句,就是把虛擬路徑轉化為物理路徑的。例如我實驗 的時候virtualPath=~/men/,而physicalPath=C:\Users\majiang\Documents\Visual Studio 2010\Projects\System.Configuration\MvcApp\men\,這個文件沒有但是目錄卻是有的。順便提一下默認情況下 CachedPathData.DoNotCacheUrlMetadata是false,在這里它主要用來控制是否使用緩存。真正查找文件和目錄是否存 在是在這句代碼完成的:

 bool flag2 = isFile ? File.Exists(physicalPath) : Directory.Exists(physicalPath);不過大家一定要注意這里默認是有緩存的,我當時做實驗的時候見 了 routes.RouteExistingFiles = true;這句也沒起到作用,就知道緩存的存在,知道這里在明白緩存是怎么搞的啊。

總結一下吧:RouteCollectiond的RouteExistingFiles屬性是:對已存在的文件和文件夾是否啟用路由,大家千萬不要忘記還有文件夾這個檢查,同時文件和文件夾的檢查結果默認是啟用了緩存的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM