public List<dynamic> GetContents(HttpContextBase httpContext) { var hostKey = httpContext.GetHostKey(); var cacheKey = "__ReadOnlyFileSystemContentProvider_" + hostKey; // todo: Verify that there is no security issue here using host this way. aka what if the host == "..\.." or something. var contents = (List<dynamic>)httpContext.Cache.Get(cacheKey); if (contents == null) { lock (_lock) { // two phase locking contents = (List<dynamic>)httpContext.Cache.Get(cacheKey); if (contents == null) { // The convention of this content provider is to look in the ~/App_Data/{host}/content folder for the content. var contentVirtualPath = httpContext.GetHostDataPath("content/"); var contentPhysicalPath = httpContext.Server.MapPath(contentVirtualPath); if (!Directory.Exists(contentPhysicalPath)) { throw new Exception("No content found for host. Host: " + hostKey); } contents = this.getContents(contentPhysicalPath); int cacheTimeoutSeconds = httpContext.GetConfigurationValue("cacheTimeoutSeconds", 0); if (cacheTimeoutSeconds > 0) { // Add the contents to the cache, using all files in the app_data folder as the cache dependency. If any app_data changes, the cache will be refreshed. This may be bad for you if you put other data in the app_data folder. httpContext.Cache.Insert(cacheKey, contents, new CacheDependency(Directory.GetDirectories(Path.Combine(contentPhysicalPath, ".."), "*", SearchOption.AllDirectories)), DateTime.UtcNow.AddSeconds(cacheTimeoutSeconds), Cache.NoSlidingExpiration); } } } } return contents; }