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;
}
}
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: