Azure CDN に Azure Web サイトのテーマを格納する方法を実装しようとしています。
ファイルを 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);