Я пытаюсь реализовать хранение тем веб-сайта Azure в Azure CDN.
Я скопировал файлы в CDN, сохранив структуру папок, как это было в исходной папке App_Themes.
Я создал VirtualPathProvider и необходимые классы Virtualdirectory и VirtualFile. Провайдер зарегистрирован в global.asax.
Моя проблема в том, что единственный файл, который, кажется, приходит из CDN, это файл скина. Все изображения, CSS и т. Д. По-прежнему ссылаются так, как если бы они были в стандартной структуре App_Themes. Если я добавлю точку останова в свой код, тогда метод Open моей VirtualTheme всегда будет вызываться только для файла скина.
Кому-нибудь удалось реализовать подобное решение?
Есть идеи, что я делаю не так?
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium)]
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.High)]
public class RedirectAppThemes : VirtualPathProvider
{
private bool IsPathVirtual(string virtualPath)
{
String checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
return checkPath.StartsWith("~/App_Themes/", StringComparison.InvariantCultureIgnoreCase);
}
public override bool FileExists(string virtualPath)
{
if (IsPathVirtual(virtualPath))
{
VirtualThemeFile file = new VirtualThemeFile(virtualPath);
return file.Exists;
}
else
{
return Previous.FileExists(virtualPath);
}
}
public override VirtualFile GetFile(string virtualPath)
{
if (IsPathVirtual(virtualPath))
{
return new VirtualThemeFile(virtualPath);
}
else
{
return Previous.GetFile(virtualPath);
}
}
public override bool DirectoryExists(string virtualDir)
{
if (IsPathVirtual(virtualDir))
{
VirtualThemeDirectory dir = new VirtualThemeDirectory(virtualDir);
return dir.Exists;
}
else
{
return Previous.DirectoryExists(virtualDir);
}
}
public override VirtualDirectory GetDirectory(string virtualDir)
{
if (IsPathVirtual(virtualDir))
{
return new VirtualThemeDirectory(virtualDir);
}
else
{
return Previous.GetDirectory(virtualDir);
}
}
public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
{
if (IsPathVirtual(virtualPath))
{
return null;
}
else
{
return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
}
}
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class VirtualThemeDirectory : VirtualDirectory
{
private string cdnPath = "http://xxxxxxxxx.blob.core.windows.net/";
public VirtualThemeDirectory(string virtualPath) : base(virtualPath)
{
}
public override IEnumerable Children
{
get
{
List<object> children = new List<object>();
string dir = this.VirtualPath.Replace("/App_Themes/", String.Empty);
CloudBlobClient client = new CloudBlobClient(cdnPath);
var blobs = client.ListBlobsWithPrefix(@"webinterfacethemes/" + dir );
foreach (CloudBlobDirectory directory in blobs.OfType<CloudBlobDirectory>())
{
VirtualThemeDirectory vtd = new VirtualThemeDirectory(directory.Uri.AbsolutePath.Replace("/webinterfacethemes/", "/App_Themes/"));
children.Add(vtd);
}
foreach (CloudBlob file in blobs.OfType<CloudBlob>())
{
VirtualThemeFile vtf = new VirtualThemeFile(file.Uri.AbsolutePath.Replace("/webinterfacethemes/", "/App_Themes/"));
children.Add(vtf);
}
return children;
}
}
public override IEnumerable Directories
{
get
{
List<object> children = new List<object>();
string dir = this.VirtualPath.Replace("/App_Themes/", String.Empty);
CloudBlobClient client = new CloudBlobClient(cdnPath);
var blobs = client.ListBlobsWithPrefix(@"webinterfacethemes/" + dir);
foreach (CloudBlobDirectory directory in blobs.OfType<CloudBlobDirectory>())
{
VirtualThemeDirectory vtd = new VirtualThemeDirectory(directory.Uri.AbsolutePath.Replace("/webinterfacethemes/", "/App_Themes/"));
children.Add(vtd);
}
return children;
}
}
public override IEnumerable Files
{
get
{
List<object> children = new List<object>();
string dir = this.VirtualPath.Replace("/App_Themes/", String.Empty);
CloudBlobClient client = new CloudBlobClient(cdnPath);
var blobs = client.ListBlobsWithPrefix(@"webinterfacethemes/" + dir);
foreach (CloudBlob file in blobs.OfType<CloudBlob>())
{
VirtualThemeFile vtf = new VirtualThemeFile(file.Uri.AbsolutePath.Replace("/webinterfacethemes/", "/App_Themes/"));
children.Add(vtf);
}
return children;
}
}
public bool Exists
{
get
{
string dir = this.VirtualPath.Replace("/App_Themes/", String.Empty);
CloudBlobClient client = new CloudBlobClient(cdnPath);
if (client.ListBlobsWithPrefix("webinterfacethemes/" + dir).Count() > 0)
return true;
else
return false;
}
}
}
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class VirtualThemeFile : VirtualFile
{
private string cdnPath = "http://xxxxxxx.vo.msecnd.net/webinterfacethemes/";
public VirtualThemeFile(string VirtualPath) : base(VirtualPath)
{
}
public override Stream Open()
{
string url = this.VirtualPath.Replace("/App_Themes/", cdnPath);
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
WebResponse myResp = myReq.GetResponse();
Stream stream = myResp.GetResponseStream();
return stream;
}
public bool Exists
{
get
{
//Check if the file exists
//do this with a HEAD only request so we don't download the whole file
string url = this.VirtualPath.Replace("/App_Themes/", cdnPath);
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
myReq.Method = "HEAD";
HttpWebResponse myResp = (HttpWebResponse)myReq.GetResponse();
if (myResp.StatusCode == HttpStatusCode.OK)
{
return true;
}
else
{
return false;
}
}
}
}
А в Global.asax Application_start:
RedirectAppThemes redirect = new RedirectAppThemes();
HostingEnvironment.RegisterVirtualPathProvider(redirect);