Я все ждал, ждал, ждал, когда же все-таки умные ребята, разрабатывающие System.Web.Optimization добавят поддержку автоматической загрузки содержимого бандла в контейнер Azure Storage. На днях вышла «1.0.0-beta2», но желаемого функционала так я и не нашел, а быстроты то хочется…
Как использовать?
<head> @BlobStorageProvider.Render("~/mainlayout", BlobStorageProvider.ContentType.Style) </head>
Как работает?
/// <summary> /// Ссылка на кеш-хранилище Blob'а /// </summary> private const string CachedStorageLink = "http://cdn.m6lab.com/{0}/{1}";
В вышеприведенном коде указана ссылка на привязанный Caching к Blob’у. Скорость отклика у Blob’а оставляет желать лучшего, поэтому рекомендую использовать Caching для получения данных из Blob’а.
Сделать override на функцию, создающую Bundle не представляется возможным, поэтому пришлось использовать костыль:
// Данные файла на сервере var content = new WebClient().DownloadString("{URL Вашего сайта}" + url);
Исходный код целиком:
public class BlobStorageProvider { /// <summary> /// Перечисление возможных типов загружаемого контента /// </summary> public enum ContentType { Script, Style } /// <summary> /// Ссылка на кеш-хранилище Blob'а /// </summary> private const string CachedStorageLink = "http://cdn.m6lab.com/{0}/{1}"; /// <summary> /// Название Blob-хранилища /// </summary> private const string ContainerName = "robofollower"; /// <summary> /// Настройки подключения к Blob'у /// </summary> private static readonly CloudStorageAccount StorageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName={Storage Account};AccountKey={Primary Key}"); /// <summary> /// Контейнер Blob'a /// </summary> private static readonly CloudBlobContainer Container = StorageAccount.CreateCloudBlobClient().GetContainerReference(ContainerName); /// <summary> /// Контейнер ссылок на CDN /// </summary> private static readonly Dictionary<string, string> CdnLinks = new Dictionary<string, string>(); /// <summary> /// Загруза данных в Blob-контейнер /// </summary> /// <param name="virtualPath"></param> /// <param name="contentType"></param> /// <returns></returns> private static void Upload(string virtualPath, ContentType contentType) { // Ссылка на файл на сервере var url = Scripts.Url(virtualPath); // Данные файла на сервере var content = new WebClient().DownloadString("{URL Вашего сайта}" + url); // Удаляем лишние знаки var formatted = url.ToString().Replace("/", "").Replace("?", "").Replace("v", "").Replace("=", "").Replace("-", ""); var blobContentType = string.Empty; // Добавляем постфикс и настраиваем контейнер switch (contentType) { case ContentType.Script: formatted += ".js"; blobContentType = "text/javascript"; break; case ContentType.Style: formatted += ".css"; blobContentType = "text/css"; break; } // Референс блоба и его настройки var blob = Container.GetBlockBlobReference(formatted); blob.Properties.CacheControl = "public, max-age=3600"; blob.Properties.ContentType = blobContentType; // Загрузка в контейнер blob.UploadFromStream(new MemoryStream(Encoding.ASCII.GetBytes(content))); // Добавляем в локальный контейнер ссылку CdnLinks.Add(virtualPath, string.Format(CachedStorageLink, ContainerName, formatted)); } public static IHtmlString Render(string virtualPath, ContentType contentType) { if (!CdnLinks.ContainsKey(virtualPath)) Upload(virtualPath, contentType); switch (contentType) { case ContentType.Style: { var tag = new TagBuilder("link"); tag.MergeAttributes(new Dictionary<string, string> { { "href", CdnLinks[virtualPath] }, { "rel", "stylesheet" } }); return new HtmlString(tag.ToString(TagRenderMode.SelfClosing)); } case ContentType.Script: { var tag = new TagBuilder("script"); tag.MergeAttributes(new Dictionary<string, string> { { "src", CdnLinks[virtualPath] } }); return new HtmlString(tag.ToString(TagRenderMode.SelfClosing)); } } return null; } }
ссылка на оригинал статьи http://habrahabr.ru/post/157597/
Добавить комментарий