We have already explored the benefits of using a CDN (Content Delivery Networks) to speed up your website, so I'll not address the matter again. If you want to know more about this, take a look at Irritated by your blog performance? Boost it using the cloud!
The problem that you are going to face if you decide to use a CDN, is that during development usually you don't want to use the CDN, rather you prefer to serve resource directly from your web site.
For example in the head section of your page you have the following markup.
<
link
href="/css/style.css" rel="stylesheet" type="text/css"/>
If you want to speed up page rendering you can download the same style sheet from the CDN
But while you are developing the web application on your machine or while there's a test version on your deployment slot, you want that the style sheet is downloaded directly from the website and not from the CDN.
Another problem may arise if you change your mind and you want to switch your CDN to another one.
How to rapidly switch from a CDN to another one without having to replace all URLs in all your pages?
How to solve this problem without hardcoding the CDN URL in your ASP.NET pages?
I'm going to share with you a smart and definitive solution that will save you tons of hours.
Use an Expression Builder!
I have developed an expression builder that allows me to use the following markup:
<
link
href="<%$ CdnUrl:/css/style.css %>" rel="stylesheet" type="text/css" />
This markup will prepend the CDN to the URL only in production and will render a local URL in all other cases.
You can use this syntax everywhere you need to serve a resource from the CDN, for example an image:
<
asp:Image
ImageUrl="<%$ CdnUrl:/images/myimage.png %>" runat="server" />
This magic is possible thanks to a class derived from ExpressionBuilder
.
namespace
IdeaR.Web.Compilation
{
/// <summary>
/// In release version prepends the CDN URL to the specified one
/// if the domain is the production one.
/// </summary>
[ExpressionPrefix(
"CdnUrl"
)]
public
class
CdnUrlExpressionBuilder : ExpressionBuilder
{
#region Operations
/// <summary>
/// Returns the evaluated expression.
/// </summary>
public
static
object
GetCdnUrl(
string
expression, Type target,
string
entry)
{
var retvalue = expression;
UriKind.Absolute);
var currentUri = HttpContext.Current.Request.Url;
// If this is a production website URL
if
(currentUri.Scheme == productionUri.Scheme &&
currentUri.Host == productionUri.Host)
retvalue = cdnUrl + expression;
return
retvalue;
}
#endregion
#region Overrides
/// <summary>
/// Returns a code expression that is used to perform the
/// property assignment in the generated page class.
/// </summary>
public
override
CodeExpression GetCodeExpression(
BoundPropertyEntry entry,
object
parsedData, ExpressionBuilderContext context)
{
var componentType = entry.DeclaringType;
var expressionArray =
new
CodeExpression[3]
{
new
CodePrimitiveExpression(entry.Expression.Trim()),
new
CodeTypeOfExpression(componentType),
new
CodePrimitiveExpression(entry.Name)
};
var descriptor = TypeDescriptor.GetProperties(componentType)
[entry.PropertyInfo.Name];
return
new
CodeCastExpression(descriptor.PropertyType,
new
CodeMethodInvokeExpression(
new
CodeTypeReferenceExpression(GetType()),
"GetCdnUrl"
, expressionArray));
}
#endregion
}
}
To register the new expression you have only to place the following declaration in the web.config file
<
compilation
>
<
expressionBuilders
>
<
add
expressionPrefix
=
"CdnUrl"
type
=
"IdeaR.Web.Compilation.CdnUrlExpressionBuilder"
/>
</
expressionBuilders
>
</
compilation
>
That's all!
You can further extend it, for example if the URL is a style sheet you can append a version number to clear the CDN cache, etc.
I hope you will enjoy this piece of code, if so leave a comment or share it!
Did you find this article useful?
If you think your friends will like it too, share it on Facebook.
You have only to press the button here below!