Question

I created a VirtualPathProvider to allow to move all the resources in a custom folder based on the Request.Host, to manage multiple domains with one web application.

On my local machine the MVC application works, when I publish to Azure I obtain a not clear error (HTTP 503) and I don't understand what I've to check to have more information.

Here the implementation of the provider:

public class PerSiteVirtualPathProvider : VirtualPathProvider
{
    private readonly IDictionary<string, string> domainToPath;

    public PerSiteVirtualPathProvider(IDictionary<string, string> domainToPath)
    {
        this.domainToPath = domainToPath;
    }

    public override bool FileExists(string virtualPath)
    {
        return base.FileExists(virtualPath) || PerSiteFileExists(virtualPath);
    }

    public override bool DirectoryExists(string virtualDir)
    {
        return base.DirectoryExists(virtualDir) || PerSiteFileExists(virtualDir);
    }

    public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies)
    {
        if (PerSiteFileExists(virtualPath))
        {
            var host = HttpContext.Current.Request.Url.Host.ToLower();

            return string.Concat(host, "/", virtualPath);
        }

        return base.GetFileHash(virtualPath, virtualPathDependencies);
    }

    public override VirtualFile GetFile(string virtualPath)
    {
        if (PerSiteFileExists(virtualPath))
        {
            var physicalPath = CombinePath(virtualPath);
            return new PhysicalVirtualFile(virtualPath, physicalPath);
        }

        return base.GetFile(virtualPath);
    }

    public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
    {
        if (PerSiteFileExists(virtualPath))
        {
            var host = HttpContext.Current.Request.Url.Host.ToLower();

            return new CacheDependency(new[] { CombinePath(virtualPath) }, new[] { host });
        }

        return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
    }

    private string CombinePath(string virtualPath)
    {
        var host = HttpContext.Current.Request.Url.Host.ToLower();

        var cleanVirtualPath = virtualPath.TrimStart('~', '/').Replace('/', '\\');

        if (!domainToPath.ContainsKey(host))
        {
            throw new InvalidOperationException(string.Format("The specified '{0} domain is not registered.", host));
        }

        var domainFolder = domainToPath[host];

        var path = Path.Combine(domainFolder, cleanVirtualPath);

        return path;
    }

    private bool PerSiteFileExists(string virtualPath)
    {
        var path = CombinePath(virtualPath);

        var fileExists = File.Exists(path);

        return fileExists;
    }
}
Was it helpful?

Solution

I solved the problem, I used the App_Data directory to read all the resources, that is not allowed for the VirtualPathProvider, see here, in particular in the Remarks paragraph:

You cannot store ASP.NET application folders or files that generate application-level assemblies in a virtual file system. This includes:

  • The Global.asax file
  • Web.config files
  • Site map data files used by the XmlSiteMapProvider
  • Directories that contain application assemblies or that generate application assemblies: Bin, App_Code, App_GlobalResources, any App_LocalResources
  • The application data folder, App_Data
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top