我正在尝试将 Azure 网站的主题存储在 Azure CDN 中。
我已将文件复制到 CDN 中,并保留了原始 App_Themes 文件夹中的文件夹结构。
我创建了一个 VirtualPathProvider 以及必要的 Virtualdirectory 和 VirtualFile 类。提供者在 global.asax 中注册。
我的问题是似乎来自 CDN 的唯一文件是皮肤文件。所有图像、css 等仍然被引用,就好像它们在标准 App_Themes 结构中一样。如果我在我的代码中设置一个断点,那么我的 VirtualTheme 的 Open 方法只会为皮肤文件调用。
有没有人设法实施这样的解决方案?
任何想法我做错了什么?
[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);