Deploy static content to a cloud-based storage service that can deliver these directly to the client. This pattern can reduce the requirement for potentially expensive compute instances.
Web applications typically include some elements of static content. This static content may include HTML pages and other resources such as images and documents that are available to the client, either as part of an HTML page (such as inline images, style sheets, and client-side JavaScript files) or as separate downloads (such as PDF documents).
Although web servers are well tuned to optimize requests through efficient dynamic page code execution and output caching, they must still handle requests to download static content. This absorbs processing cycles that could often be put to better use.
In most cloud hosting environments it is possible to minimize the requirement for compute instances (for example, to use a smaller instance or fewer instances), by locating some of an application’s resources and static pages in a storage service. The cost for cloud-hosted storage is typically much less than for compute instances.
When hosting some parts of an application in a storage service, the main considerations are related to deployment of the application and to securing resources that are not intended to be available to anonymous users.
Consider the following points when deciding how to implement this pattern:
This pattern is ideally suited for:
This pattern might not be suitable in the following situations:
Note: |
It is sometimes possible to store a complete website that contains only static content such as HTML pages, images, style sheets, client-side JavaScript files, and downloadable documents such as PDF files in a cloud-hosted storage. For more information see An efficient way of deploying a static web site on Microsoft Azure on the Infosys blog. |
Static content located in Azure blob storage can be accessed directly by a web browser. Azure provides an HTTP-based interface over storage that can be publicly exposed to clients. For example, content in a Azure blob storage container is exposed using a URL of the form:
http://[ storage-account-name ].blob.core.windows.net/[ container-name ]/[ file-name ]
When uploading the content for the application it is necessary to create one or more blob containers to hold the files and documents. Note that the default permission for a new container is Private, and you must change this to Public to allow clients to access the contents. If it is necessary to protect the content from anonymous access, you can implement the Valet Key pattern so users must present a valid token in order to download the resources.
Note: |
The page Blob Service Concepts on the Azure website contains information about blob storage, and the ways that you can access it and use it. |
The links in each page will specify the URL of the resource and the client will access this resource directly from the storage service. Figure 1 shows this approach.
Figure 1 - Delivering static parts of an application directly from a storage service
The links in the pages delivered to the client must specify the full URL of the blob container and resource. For example, a page that contains a link to an image in a public container might contain the following.
HTML
<img src="http://mystorageaccount.blob.core.windows.net/myresources/image1.png" alt="My image" />
Note: |
If the resources are protected by using a valet key, such as an Azure Shared Access Signature (SAS), this signature must be included in the URLs in the links. |
The examples available for this guide contain a solution named StaticContentHosting that demonstrates using external storage for static resources. The StaticContentHosting.Cloud project contains configuration files that specify the storage account and container that holds the static content.
XML
<Setting name="StaticContent.StorageConnectionString" value="UseDevelopmentStorage=true" /><Setting name="StaticContent.Container" value="static-content" />
The Settings class in the file Settings.cs of the StaticContentHosting.Web project contains methods to extract these values and build a string value containing the cloud storage account container URL.
C#
public class Settings{ public static string StaticContentStorageConnectionString { get { return RoleEnvironment.GetConfigurationSettingValue( "StaticContent.StorageConnectionString"); } } public static string StaticContentContainer { get { return RoleEnvironment.GetConfigurationSettingValue("StaticContent.Container"); } } public static string StaticContentBaseUrl { get { var account = CloudStorageAccount.Parse(StaticContentStorageConnectionString); return string.Format("{0}/{1}", account.BlobEndpoint.ToString().TrimEnd('/'), StaticContentContainer.TrimStart('/')); } }}
The StaticContentUrlHtmlHelper class in the file StaticContentUrlHtmlHelper.cs exposes a method named StaticContentUrl that generates a URL containing the path to the cloud storage account if the URL passed to it starts with the ASP.NET root path character (~).
C#
public static class StaticContentUrlHtmlHelper{ public static string StaticContentUrl(this HtmlHelper helper, string contentPath) { if (contentPath.StartsWith("~")) { contentPath = contentPath.Substring(1); } contentPath = string.Format("{0}/{1}", Settings.StaticContentBaseUrl.TrimEnd('/'), contentPath.TrimStart('/')); var url = new UrlHelper(helper.ViewContext.RequestContext); return url.Content(contentPath); }}
The file Index.cshtml in the Views\Home folder contains an image element that uses the StaticContentUrl method to create the URL for its src attribute.
HTML
<img src="@Html.StaticContentUrl("~/Images/orderedList1.png")" alt="Test Image" />
The following pattern may also be relevant when implementing this pattern:
Valet Key Pattern. If the target resources are not supposed to be available to anonymous users it is necessary to implement security over the store that holds the static content. The Valet Key pattern describes how to use a token or key that provides clients with restricted direct access to a specific resource or service such as a cloud-hosted storage service.