The best way to switch between static assets and CDN-based resources for development and deployment

I am developing an application and an application in ASP.NET MVC3. I plan to take advantage of Amazons Cloudfront as a CDN for serving static assets.

I am wondering if someone has developed an easy way to switch between local development resources and CDN-based resources for deployment?

Any advice or recommendations are appreciated.

+7
source share
5 answers

Similar to how Paul answers.

In the past, I used the extension method for UrlHelper, which created links based on the value from web.config.

This is useful, so you do not need to miniaturize your views after publishing, and it is as simple as updating the web.config entry for publishing. Any resources that require the use of a CDN resource, you simply say Url.CdnContent("~/site.css")

I'm not currently on my development computer, but when I get home I will give you a source for my extension method

This is very simplistic, but it works for what I need.

 public static string CdnContent(this UrlHelper helper, string relativePath) { var cdnRoot = ConfigurationManager.AppSettings["cygnus.cdnroot"]; if (string.IsNullOrEmpty(cdnRoot)) return UrlHelper.GenerateContentUrl(relativePath, helper.RequestContext.HttpContext); if (relativePath.StartsWith("~")) relativePath = relativePath.Substring(1); if (cdnRoot.EndsWith("/")) cdnRoot = cdnRoot.Substring(0, cdnRoot.Length - 1); if (!relativePath.StartsWith("/")) relativePath = "/" + relativePath; return cdnRoot + relativePath; } 
+7
source

I have done this in the past using a few simple rules:

  • Always use relative file paths in CSS
  • Always use the standard template for linking to content in your views (I use relative application paths with Url.Content , ie Url.Content("~/content/file.jpg") )
  • Do not link to files in JavaScript.

Then, in my deployment process, I can simply copy all the static resources from the site to the CDN, CSS will work only after its relative values ​​(CSS url() always refer to the CSS file in which they are located, and not to the request), and I will use regex to replace any lines in my views that are in the form that I expect to have a base CDN path.

+4
source

Good question. I suggest you use compilation conditional variables .

If your project is in debug mode, local assets will be linked. If your project is in release mode , CDN assets will be linked.

Here is an example:

 <head runat="server"> <% #if DEBUG %> <link rel="stylesheet" type="text/css" href="/Assets/Styles/Default.css" /> <% #else %> <link rel="stylesheet" type="text/css" href="http://cdn.mysite.com/Assets/Styles/Default.css" /> <% #endif %> </head> 

But be careful when you publish a project , it should be in release mode . Once I updated one of my projects, and it was in DEBUG mode, and everything went wrong.

Here are some good conditional compilation links:

http://haacked.com/archive/2007/09/16/conditional-compilation-constants-and-asp.net.aspx

http://odetocode.com/blogs/scott/archive/2005/12/01/conditional-compilation-in-asp-net-2-0.aspx

http://odetocode.com/blogs/scott/archive/2007/09/24/more-on-conditional-compilation-in-asp-net.aspx

+2
source

I have a set of extension methods that I use (see below). You can use them as a base / example to create your own debug / release extension methods.

General debugging / release:

 public static MvcHtmlString DebugReleaseString(this System.Web.Mvc.HtmlHelper html, string debugString, string releaseString) { string toReturn = debugString; #if !DEBUG if (!string.IsNullOrEmpty(releaseString)) toReturn = releaseString; #endif return MvcHtmlString.Create(toReturn); } 

General debug / release usage:

 @Html.DebugReleaseString("/images/myimage.jpg", "http://mycdn.com/images/myimage.jpg") 

CSS debug / release tags:

 public static MvcHtmlString CssTag(this System.Web.Mvc.HtmlHelper html, string fileName) { return html.CssTag(fileName, string.Empty); } public static MvcHtmlString CssTag(this System.Web.Mvc.HtmlHelper html, string fileName, string releaseFileName) { if (string.IsNullOrEmpty(fileName)) throw new ArgumentNullException("fileName"); string cssTag = string.Format( "<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}\" />", html.MeDebugReleaseString(fileName, releaseFileName)); return MvcHtmlString.Create(cssTag); } 

Using CSS tags for debugging / release:

 @Html.CssTag("/styles/mystyle.css") @Html.CssTag("/styles/mystyle.css", "http://mycdn.com/styles/mystyle.css") 

JS Debug / Release Tags:

 public static MvcHtmlString JavascriptTag(this System.Web.Mvc.HtmlHelper html, string fileName) { return html.JavascriptTag(fileName, string.Empty); } public static MvcHtmlString JavascriptTag(this System.Web.Mvc.HtmlHelper html, string fileName, string releaseFileName) { if (string.IsNullOrEmpty(fileName)) throw new ArgumentNullException("fileName"); string jsTag = string.Format("<script type=\"text/javascript\" src=\"{0}\"></script>", html.MeDebugReleaseString(fileName, releaseFileName)); return MvcHtmlString.Create(jsTag); } 

Using Jug tags for debugging / release:

 @Html.JavascriptTag("/scripts/myscript.css") @Html.JavascriptTag("/scripts/myscript.css", "http://mycdn.com/scripts/myscript.js") 

Additional debugging / release options:

 public enum RenderModeEnum { Debug, Release, DebugAndRelease } public static MvcHtmlString CssTag(this System.Web.Mvc.HtmlHelper html, string fileName, RenderModeEnum tagRenderMode) { if (tagRenderMode == RenderModeEnum.DebugAndRelease) return html.CssTag(fileName); #if DEBUG if (tagRenderMode == RenderModeEnum.Debug) return html.CssTag(fileName); #else if (tagRenderMode == RenderModeEnum.Release) return html.CssTag(fileName); #endif return MvcHtmlString.Empty; } public static MvcHtmlString JavascriptTag(this System.Web.Mvc.HtmlHelper html, string fileName, RenderModeEnum tagRenderMode) { if (tagRenderMode == RenderModeEnum.DebugAndRelease) return html.JavascriptTag(fileName); #if DEBUG if (tagRenderMode == RenderModeEnum.Debug) return html.JavascriptTag(fileName); #else if (tagRenderMode == RenderModeEnum.Release) return html.JavascriptTag(fileName); #endif return MvcHtmlString.Empty; } 

Additional features for using debugging / release:

 @Html.CssTag("/styles/mystyle.css", RenderModeEnum.DebugAndRelease) @Html.CssTag("/styles/mystyle.css", RenderModeEnum.Debug) @Html.CssTag("http://mycdn.com/styles/mystyle.css", RenderModeEnum.Release) 
+1
source

I developed a library specifically to solve this problem.

https://github.com/vincpa/mvc.resourceloader

+1
source

All Articles