Scott Hanselman

Redirecting ASP.NET Legacy URLs to Extensionless with the IIS Rewrite Module

May 10, '13 Comments [19] Posted in ASP.NET | IIS
Sponsored By

ASP.NET has included support for "friendly URLs" for a while now. ASP.NET MVC has always supported friendly URLs and more recently, so has Web Forms. That means if you don't want to have the .aspx extension, you certainly don't have to.

However, there's a LOT of existing legacy apps out there as well as apps that you may not have full control over. For example, there's a site that I want to influence but it's got dozens (hundreds) of links to foo.html and bar.html existing pages.

Legacy (n): A super-fancy way of saying "already exists."

What I want to do is kind of sloppy and I'm doing it for aesthetic reasons. I'll hopefully get around to updating the site's links later and know that future links will be extensionless. But look at me, I'm justifying why I'm doing this, Dear Reader. You of all people know that sometimes you just gotta do something just because ya gotta Get It Done™©.

I want to:

  • redirect existing GETs to a /foo.html to /foo
    • Redirects are external
  • but, keep rewriting /foo to the underlying /foo.html so it handles the request
    • Rewrites are internal

I can do all this within my web.config using the IIS Url Rewrite Module.  I can do this with ANY file type that IIS can handle, meaning this isn't an ASP.NET-specific thing. This all happens well before your application gets involved. You'll note I did a similar thing with a PHP app running under IIS just last month.

Here's what my web.config looks like. Note that since I have Azure (or in just IIS 7+ and the Rewrite module) I just added this file. There was no configuration needed. The same would apply to any existing site. Be aware that sometimes super-"greedy" rewrite or redirect rules can end up grabbing ahold of your CSS or JS so you'll want to be aware if something odd happens.

<?xml version="1.0" encoding="UTF-8"?>
<rule name="extensionless" stopProcessing="true">
<match url="(.*)\.html$" />
<action type="Redirect" url="{R:1}" redirectType="Permanent" />
<rule name="removeextension" enabled="true">
<match url=".*" negate="false" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{URL}" pattern="(.*)\.(.*)" negate="true" />
<action type="Rewrite" url="{R:0}.html" />

This stuff is hard to write, though.

SIDE NOTE: My RegEx expert Ruslan points out that the final Action could be simplified slightly like this:

<add input="{URL}" pattern="\." negate="true" />

This stuff is also hard to test. The IIS Rewrite module has a great UI for IIS that will write a lot of these rules for you and let you test them interactively:

URL Rewrite module in IIS

Hope this helps. I wrote this post (and bookmarked it) for myself because I am always googling around for this particular rule to remind myself. Now I'll search my own blog. ;) Reason #64 to blog, friends.

SPONSOR: Big thanks to the feed sponsor this past week, Ext.NET (seriously, check out their demos, really amazing stuff!) - Quickly build modern WebForm and MVC (including RAZOR) Apps for ASP.NET. Free pancake breakfast with all purchases!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Smart Watches are finally going to happen - Pebble Watch Reviewed

May 8, '13 Comments [41] Posted in Reviews
Sponsored By
iPod nano, Pebble, TI and SPOT Watch - I had to photoshop the SpotWatch as the battery died long ago

The Pebble Watch is shipping and it's revolutionary, fresh and new! Well, kind of. Dick Tracy got his first smart watch in 1946. It seems we've always wanted a computer and communicator on our wrists. I remember wanting to buy a TV watch in the 80s and we all had Casio Databank watches growing up (well, the nerds did).

Animated Pebble Watch FacesThe history of smart watches goes back much further of course as Microsoft Researcher Bill Buxton points out. He has a collection of smart watches going back almost 40 years!

My buddy Karl still wears and uses his Timex Datalink watch, originally made in 1994. Almost ten years ago I bought a Microsoft SPOT Watch from Fossil and loved every minute of it. It had news, sports, stocks, weather and the occasional email. However it didn't connect to my phone (it was mostly PalmPilots back then, and the occasional Blackberry pager) and Bluetooth wasn't a thing quite yet.

Smart Phone sales are flattening out as, well, everyone who wants one has one. There's only so many things you can sell with batteries, screens, and wireless technology, right? Moreover, young people don't wear watches! I'm a watch guy, myself, with a watch case and a growing collection. I like watches old and new. I'm often teased by my younger co-workers who declare "my phone is my watch! Why would I want something else to carry around?" Watches are such an outmoded concept, right?

I for one, think that the wrist is the next big thing. This is a market that's right on the edge of mainstream adoption and has been for at least a decade, if not the for the last 70 years!

The Pebble Smart Watch

I was a backer of the Pebble's Kickstarter campaign and my red Pebble showed up last week. It's worth noting that Kickstarter isn't a store or marketplace, but rather a place you invest in an idea and watch it grow. Many Kickstarters fail. You might invest your money and never see a return on your investment. Fortunately, the Pebble succeeded and almost a year later my investment arrived.

The Pebble Box, closed The Pebble Box, opened

The boxing was very Kindle-esque and classy in its recycled granola-ness. It was simple and served its purpose well. The package included just the watch and the charging cable. Sadly, the charging cable is custom with an unnecessarily clever (and weak) magnetic connector. I'd have preferred a micro-USB port (and in fact, would for every device) so that I might travel with yet-another-unique-cable-I-can't-afford-to-lose-can't-tell-apart-at-a-distance-and-will-eventually-lose-in-my-bad. But I'm not bitter.

Initial Impressions

The Pebble is easy to view in sunlight The Pebble shows fingerprints, but looks great, if a little plasticky

The watch is lovely. Truly. Considering that I paid $125 for it - a reasonable price considering its potential - I'm happy with it and would recommend it. Still, it It's plastic. It's light. It's glossy and smears easily. I'm afraid it will crack or scratch if I bump whilst walking. It's fine, but it's not, well, it's not an Apple Product. It's not made of magical Surface Magnesium. It's a plastic watch with a rubber wristband.

It's a little too tall, for my taste. This causes the Pebble to be a half-inch taller than the average (read: my) wrist, causing it to stick out just enough that I notice it. I prefer the wider square style of the iPod "watch." The Pebble is not at all unattractive, but I'm assume the creators must be thick-wristed people to not have noticed this.

photo The iPod Nano is a fancier watch with a color touch screen, but no connectivity 

What do we really want? Something with the intense attention to detail and built quality of an Apple iPod Nano 6th generation combined with a Lunatik Watch Strap. Now THAT'S a fantastic watch.

The idea of an iWatch is an attractive one...and the combination of what you get today with a Pebble combined with what you get with a (now discontinued) iPod Nano is near-ideal.

The Pebble gets you:

  • Low-power Bluetooth 4 connectivity
  • An open SDK
  • Reasonable battery life of a few days
  • Vibrations
  • Motion-activated backlight
  • Potential!
  • a 144x168 1-bit display

The iPod Nano (6th generation) "watch" gets you:

  • Fantastic build quality
  • A color screen
  • Touch!
  • FM Radio, Photos, Music, Headphone Jack
  • Pedometer
  • Crappy battery life of a day at best
  • a 240x240 color TFT display

The Pebble effectively gives us connectivity and an SDK. If the iWatch does come - and it will - it better have all these things. Although, I expect it won't have an open SDK (Watch App Store anyone?) and it won't play well with Android as the Pebble does. Therefore, iOS people will get iWatches, and Android people will get Pebbles. Check back in six months and we shall see!

What the Pebble does for an iPhone

My main phone is an iPhone 4s. Pebble really shine on Android, I am told, as the open Android OS gives developers free reign. Still, I've been very happy with the device exactly as it is, even if it didn't improve...and it will.

Today the Pebble is a Bluetooth-connected watch that will give you:

  • Vibration notifications and the full text of SMS texts sent to your phone.
    • This is brilliant, and it's the vibration that is the key. I was in the movies just this evening and got a text from the babysitter. The watch discretely let me see that it wasn't urgent without removing my phone from my pocket.
    • SMS notifications are totally reliable on the Pebble with iOS but email notifications barely work. They say they'll fix this soon.
  • Clear, backlit display
    • Go into settings, and turn on Motion Activated Backlight and the Pebble will light up with a gentle shake. This was nice at the movies tonight.
  • Customizable watch faces on a clear screen that is visible in total darkness (due to its backlight) and in bright sunlight (due to its low-power memory LCD).
    • It's great to be able to change the LCD screen with new watch faces, but I admit I'd have appreciated plastic colorful watch covers. It's nice I have a red Pebble, but it's forever red. Why not make the face swappable?
  • Answer and Hang-up the Phone
    • When paired with a Bluetooth headset, this means you can get a call, glance at your watch, see who it is, and answer it without touching your phone. iOS doesn't show the name, just the number. Again, we shall see.

This is the Pebble today. Tomorrow promises apps and better notifications.

Selecting Watch faces The Pebble is connected to my iPhone

What Pebble Needs

The Pebble needs what my SPOT Watch had ten years ago. I want:

  • Weather alerts
    • How about Dark Sky weather alerts on my Pebble? Surely they are working on a notification bridge for 3rd party apps?
  • News, Stocks
    • Breaking news and Stock price alerts would be lovely.
  • Quick SMS responses
    • "I'll call you back" and a few quick choices for responses to texts would be a nice time saver.
  • Motion details...speedometer, GPS, etc
    • This would all be using the Pebble as a "remote view" of an app that is doing the right work, but would be great for exercise.
  • Calendar
    • What's my next appt? Give me Google Now, but on my watch.

The Pebble is typically thick compared to other Smart Watches You can change up your Pebble Watch Face with your mood

The Future of Pebble is Bright

Give people an easy to use SDK and let them download (side-load) apps directly to their device and you'll get a thriving community in no time, and that's what Pebble has done. Watch faces are written in tight "C" and move PNGs around, usually. There's lots of info at One way apps are now starting to show up with two-way apps coming soon (although Pebble will be limited on iOS due to Apple-imposed limitations). Also, there's dozens of great watch faces you can get at You can download Pebble Watch Faces directly from your phone which acts as a bridge to the watch. The experience is two clicks, really clean and simple.

Smart Watches are the next big thing. You watch.

SPONSOR: Big thanks to the feed sponsor this week, Ext.NET (seriously, check out their demos, really amazing stuff!) - Quickly build modern WebForm and MVC (including RAZOR) Apps for ASP.NET. Free pancake breakfast with all purchases!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

One ASP.NET: Nancy.Templates for Visual Studio

May 6, '13 Comments [32] Posted in ASP.NET | Open Source
Sponsored By
NancyFX inside Visual Studio

I hope you've updated to Visual Studio 2012.2 and picked up Web Essentials because we're continuing to add goodness all the time. As we march forward with the One ASP.NET vision, so does the community. One of the major goals has been to make it easier for the community to not only make templates but also live alongside ASP.NET templates as peers. This has been historically hard. It's still too complex, in fact, but it's easier than before. I'm hoping that one day soon making templates will be as easy as making and sharing NuGet packages.

Not only is most of ASP.NET open source, but so are the Azure SDKs, NuGet and more. However, there's a large and rich world of open source frameworks and projects that some companies never get to use either because their company isn't into Open Source or because they won't use code that doesn't come from Microsoft.

Additionally, Microsoft, IMHO, has done a poor job (as a collective) letting developers know that there are options and options are good. Personally, I don't care if you use Entity Framework, or Web Forms, or MVC or Web API. You can use NHibernate, Nancy, Simple.Web, ServiceStack and OpenRasta. It makes no difference to me or my organization. If you are happy and using .NET, then I'm happy and that's great. Microsoft want you to use Azure and Windows, I'm sure, but after that ultimately the rest is just the details of your stack. You should explore the options available and work within your organization to be successful.

On the topic of options, NancyFx is an open source web framework for .NET that uses the Ruby Framework "Sinatra" as its inspiration. (Get it? Frank Sinatra's daughter is Nancy Sinatra.)

A few days ago (with some gentle prodding, and some great team effort) the NancyFx team created a VSIX to integrate the NancyFx Web Framework into the Visual Studio project dialog. (You can also get NancyFx from NuGet, of course.)

It's totally simple from your point of view, as it should be. Download the VSIX, and double click on it. Done.

Installing NancyFX into Visual Studio

Now, in Visual Studio, just File | New Project and  you've got more choices!

NancyFX in the Visual Studio File New Project Dialog

Nancy is a very lightweight and flexible framework for web sites and services. You don't even need ASP.NET proper. You can self-host in your own services or exe, or host within ASP.NET. You can use Razor syntax or choose other View Engines.

Here's Hello World:

public class SampleModule : Nancy.NancyModule
public SampleModule()
Get["/"] = _ => "Hello World!";

Interesting and very concise convention, eh? The Get["/"] syntax is a route, saying that an HTTP GET for / should be handled by this => anonymous method. It's all C#, mind you!

Here's the next step, passing a model into a View:

 public class SampleModule : NancyModule
public SampleModule()
Get["/"] = parameters => {
var person = new Person {
Id = 1,
Name = "Scott Hanselman",
Content = "Lorem ipsum...",
Tags = {"c#", "aspnet", "oss", "nancy"}

return View["Index", person];

Nice, eh? Very familiar if you're comfortable with ASP.NET MVC and general MVC-style frameworks. 

If you want to return Json, you can take an object and call AsJson() like this:

Get["/person"] = parameters =>
var person = new
Id = 1,
Name = "Scott Hanselman",
Content = "Lorem ipsum..."
return Response.AsJson(person);

UPDATE: I am reminded by commenters that Nancy now supports Content Negotiation ("conneg") and will automatically return the format that the client requested. This means if your HTTP headers say "accept: application/json" then you'll get JSON back automatically. Lovely, and no need for the AsJson() (unless that's what you wanted).

There's samples you can see at and you are encouraged to add your own sample. Just File | New Project, and make a Nancy Demo Application and follow the instructions.

NancyFx has a great community of users and you'll  often find them chatting on Jabbr or in their Google Group. There's even a Resharper Plugin for Nancy. Nancy also runs nicely on Mac with Mono and MonoDevelop.

Kudos and congrats to the Nancy team for being awesome, and for making these templates.

Related Links

SPONSOR: Big thanks to the feed sponsor this week, Ext.NET (seriously, check out their demos, really amazing stuff!) - Quickly build modern WebForm and MVC (including RAZOR) Apps for ASP.NET. Free pancake breakfast with all purchases!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Penny Pinching in the Cloud: Enabling New Relic Performance Monitoring on Windows Azure Websites

May 2, '13 Comments [13] Posted in ASP.NET | Azure
Sponsored By
New Relic view of my Website

I've been looking for ways to save money running my (now 12) websites in the cloud lately. Getting insights from logs has been helpful, but I really want more details as to what my app is doing so that I might do less of it. Remember the secret of scaling an application.

Have your app do as little as possible. If you do nothing, you can scale infinitely.

I like to use tools like Glimpse to profile my apps, check database calls, and explore what's really going on. If you like application insights you may be familiar with New Relic. They are a clever system that profiles apps of all kinds, including sites ASP.NET and Azure.

I tweeted this afternoon for folks to hit my site and help me test New Relic. My lovely friends on Twitter promptly DDOS'ed my site and I respect them all the more for it.

You can actually see my site getting loaded up in this chart, and see when I scaled up within Azure and switched from Shared to Reserved. The orange instance is shared, and the blue is a NEW instances when I switched to a Reserved VM. At this point, I had enough power to weather the storm. Thanks Twitter!My site getting beaten on

How did I setup New Relic on my Web Site? New Relic happens to have an office in Portland (where I live) so I went to visit today. Coincidentally (true story) their support for Azure Web Sites has sneaked out from a closed beta to an open one recently, so I decided to hide out and see if I could add New Relic performance and application monitoring to the podcast site.

Adding New Relic to your Azure account

Login to the Azure Portal, click on New, then Store, then New Relic from within the Store.

Adding New Relic to my Azure Portal

Pick the free plan. You can have a free plan forever, they say. It doesn't include some "bells and whistles" and a storage of large amounts of historical data, but is otherwise quite functional. Plus you get a free 14-day trial (no credit card needed) of their Pro stuff.

Screenshot (19)

Create the Add-On. They tell me the Data Center Location for New Relic doesn't matter, as you are just going to get a license key.

NOTE: If you already have a New Relic license key and existing billing relationship the you don't have to use the store or add an add-on. You can use your existing license key. However, I want my billing centralized, so any bill from New Relic will go through my Azure account. It's up to you.

Adding New Relic

Now, from within the Azure dashboard, click the new New Relic node. You can click Manage to automatically move over (and automatically single sign on) to the New Relic system dashboard. Note also the Connection Info button there. We'll need that in a minute.

New Relic within the Azure Dashboard

If you click Manage and head over to the New Relic side you'll get a Welcome Message but you won't actually SEE anything interesting until your app has successfully made its first call to their system. You can check out their .NET docs if you like. They are in flux and not entirely accurate, but they'll get there.

We need to setup our Azure Website with some environment info, then add the New Relic NuGet package.

Staying with the Azure Portal, go to the Web Site you're going to instrument, and click Configuration and setup these Configuration Values. This hooks up the New Relic production profiler to the CLR. You can keep this running all the time, and it's easy to turn off.

Add these name/value pairs:

  • COR_PROFILER -{71DA0A04-7777-4EC6-9643-7D28B46A8A41}
  • COR_PROFILER_PATH - C:\Home\site\wwwroot\newrelic\NewRelic.Profiler.dll
  • NEWRELIC_HOME - C:\Home\site\wwwroot\newrelic

Your app settings will look like this in your website config within the Azure Portal:

Azure Website Config with New Relic

Make sure you not only Save your config, but also (at least once) do a complete RESTART for New Relic to get a chance to hook in.

Add New Relic to your Web Site

Install the NewRelicWindowsAzure Nuget package using the NuGet Package Manager Console using this command:

Install-Package NewRelic.Azure.WebSites

The website for is running on ASP.NET Web Pages and was written with WebMatrix so I used the NuGet GUI. You can tell that this package JUST got uploaded at the time of this writing as there's only 11 downloads!

New Relic NuGet Package

Install this package and it'll lay down a few DLLS and your newrelic.config file. Go into the newrelic.config and copy in the license key from Connection Info (remember that? It's in the Azure Portal and pictured above) into the  config file. Also update your Application Name to some useful value as that's going to identify your site in the New Relic dashboard.

Here I am publishing my site up to Azure. Only the NewRelic agent dlls that I just NuGet'ed in to my app are being published (and a random jpg I forgot).

Publishing the New Relic Agent to Azure

Once I deployed the site and hit it, I could see Hanselminutes appear within the New Relic system.

Hanselminutes within NewRelic

Here's some of the data I could access now! I can see an updated graph of where my time is being spent, both server side AND browser side.

Response Time

I can see which pages load fast and which don't, and exactly why.

Screenshot (45)

I can see SQL Queries and how long they took, what connections were opened...

Screenshot (48)

And deep timelines showing not just where my time was spend in my application, but also where it was spent in the .NET Framework AND CLR itself!

Screenshot (50)

And of course, I can see Stack Traces of problems with my code.

Screenshot (53)

This just scratches the surface, really, but I'm stoked I was able to get the free New Relic tier setup on Azure Websites in just about 10 minutes. I found two spots where four SQL calls could possibly be collapsed into one. I also found a common (and dumb, on my part) ArgumentNullException that I'd been missing for weeks.

I'm pretty impressed with their offering. I think the Pro Tier is a little spendy for the small indie developer, but cheap for the pro dev. I'd like to see a $5 or $10 tier for small hobbyist sites but for now, Free is going to serve me very nicely.

Now I'm going to go and instrument my other sites!

Related Links

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

CDNs fail, but your scripts don't have to - fallback from CDN to local jQuery

April 30, '13 Comments [46] Posted in ASP.NET | Javascript
Sponsored By

CDN issues in the Northeast

There's a great website called that serves as a reminder to me (and all of us) that external dependencies are, in fact, external. As such, they are calculated risks with tradeoffs. CDNs are great, but for those minutes or hours that they go down a year, they can be super annoying.

I saw a tweet today declaring that the ASP.NET Content Delivery Network was down. I don't work for the CDN team but I care about this stuff (too much, according to my last performance review) so I turned twitter to figure this out and help diagnose it. The CDN didn't look down from my vantage point.

I searched for things like "ajax cdn,"microsoft cdn," and " cdn down" and looked at the locations reported by the Twitter users in their profiles. They had locations like CT, VT, DE, NY, ME. These are all abbreviations for states in the northeast of the US. There were also a few tweets from Toronto and Montreal. Then, there was one random tweet from a guy in Los Angeles on the other side of the country. LA doesn't match the pattern that was developing.

I tweeted LA guy and asked him if he was really in LA or rather on the east coast.

Bingo. He was VPN'ed into Massachusetts (MA). I had a few folks send me tracerts and sent them off to the CDN team who fixed the issue in a few minutes. There was apparently a bad machine in Boston/NYC area that had a configuration change specific to the a certain Ajax path that had gone undetected by their dashboard (this has been fixed and only affected the Ajax part of the CDN in this local area).

More importantly, how can we as application developers fallback gracefully when an external dependency like a CDN goes down? Just last week I moved all of my Hanselminutes Podcast images over to a CDN. If there was a major issue I could fall back to local images with a code change. However, if this was a mission critical site, I should not only have a simple configuration switch to fallback to local resources, but I should also test and simulate a CDN going down so I'm prepared when it inevitably happens.

With JavaScript we can detect when our CDN-hosted JavaScript resources like jQuery or jQuery UI aren't loaded successfully and try again to load them from local locations.

Falling back from CDN to local copies of jQuery and JavaScript

The basic idea for CDN fallback is to check for a type or variable that should be present after a script load, and if it's not there, try getting that script locally. Note the important escape characters within the document.write. Here's jQuery:

<script src=""></script>
if (typeof jQuery == 'undefined') {
document.write(unescape("%3Cscript src='/js/jquery-2.0.0.min.js' type='text/javascript'%3E%3C/script%3E"));

Or, slightly differently. This example uses protocol-less URLS, checks a different way and escapes the document.write differently.

<script src="//"></script>
<script>window.jQuery || document.write('<script src="js/jquery-2.0.0.min.js">\x3C/script>')</script>

If you are loading other plugins you'll want to check for other things like the presence of specific functions added by your 3rd party library, as in "if (type of $.foo)" for jQuery plugins.

Some folks use a JavaScript loader like yepnope. In this example you check for jQuery as the complete (loading) event fires:

load: '',
complete: function () {
if (!window.jQuery) {

Even better, RequireJS has a really cool shorthand for fallback URLs which makes me smile:

enforceDefine: true,
paths: {
jquery: [
//If the CDN location fails, load from this location

require(['jquery'], function ($) {

With RequireJS you can then setup dependencies between modules as well and it will take care of the details. Also check out this video on Using Require.JS in an ASP.NET MVC application with Jonathan Creamer.

Updated ASP.NET Web Forms 4.5 falls back from CDN automatically

For ASP.NET Web Forms developers, I'll bet you didn't know this little gem. Here's another good reason to move your ASP.NET sites to ASP.NET 4.5 - using a CDN and falling back to local files is built into the framework.

(We've got this for ASP.NET MVC also, keep reading!)

Fire up Visual Studio 2012 and make a new ASP.NET 4.5 Web Forms application.

When using a ScriptManager control in Web Forms, you can set EnableCdn="true" and ASP.NET will automatically change the <script> tags from using local scripts to using CDN-served scripts with local fallback checks included. Therefore, this ASP.NET WebForms ScriptManager:

<asp:ScriptManager runat="server" EnableCdn="true">
<asp:ScriptReference Name="jquery" />
<asp:ScriptReference Name="jquery.ui.combined" />

...will output script tags that automatically use the CDN and automatically includes local fallback.

<script src="" type="text/javascript"></script>
<script type="text/javascript">
(window.jQuery)||document.write('<script type="text/javascript" src="Scripts/jquery-1.8.2.js"><\/script>');//]]>

<script src="" type="text/javascript"></script>
<script type="text/javascript">
(!!window.jQuery.ui && !!window.jQuery.ui.version)||document.write('<script type="text/javascript" src="Scripts/jquery-ui-1.8.24.js"><\/script>');//]]>

What? You want to use your own CDN? or Googles? Sure, just make a ScriptResourceMapping and put in whatever you want. You can make new ones, replace old ones, put in your success expression (what you check to make sure it worked), as well as your debug path and minified path.

var mapping = ScriptManager.ScriptResourceMapping;
// Map jquery definition to the Google CDN
mapping.AddDefinition("jquery", new ScriptResourceDefinition
Path = "~/Scripts/jquery-2.0.0.min.js",
DebugPath = "~/Scripts/jquery-2.0.0.js",
CdnPath = "",
CdnDebugPath = "",
CdnSupportsSecureConnection = true,
LoadSuccessExpression = "window.jQuery"

// Map jquery ui definition to the Google CDN
mapping.AddDefinition("jquery.ui.combined", new ScriptResourceDefinition
Path = "~/Scripts/jquery-ui-1.10.2.min.js",
DebugPath = "~/Scripts/jquery-ui-1.10.2.js",
CdnPath = "",
CdnDebugPath = "",
CdnSupportsSecureConnection = true,
LoadSuccessExpression = "window.jQuery && window.jQuery.ui && window.jQuery.ui.version === '1.10.2'"

I just do this mapping once, and now any ScriptManager control application-wide gets the update and outputs the correct fallback.

<script src="" type="text/javascript"></script>
<script type="text/javascript">
(window.jQuery)||document.write('<script type="text/javascript" src="Scripts/jquery-2.0.0.js"><\/script>');//]]>

<script src="" type="text/javascript"></script>
<script type="text/javascript">
(window.jQuery && window.jQuery.ui && window.jQuery.ui.version === '1.10.2')||document.write('<script type="text/javascript" src="Scripts/jquery-ui-1.10.2.js"><\/script>');//]]>

If you want to use jQuery 2.0.0 or a newer version than what came with ASP.NET 4.5, you'll want to update your NuGet packages for ScriptManager. These include the config info about the CDN locations. To update (or check your current version against the current) within Visual Studio go to Tools | Library Package Manager | Manage Libraries for Solution, and click on Updates on the left there.


Updated ASP.NET Web Optimization Framework includes CDN Fallback

If you're using ASP.NET MVC, you can update the included Microsoft.AspNet.Web.Optimization package to the -prerelease (as of these writing) to get CDN fallback as well.

Get Optimization Updates by "including PreRelease"

Note that I've on the Updates tab within the Manage NuGet Packages dialog but I've selected "Include Prerelease."

Now in my BundleConfig I can setup my bundles to include not only the CdnPath but also a CdnFallbackExpression:

public static void RegisterBundles(BundleCollection bundles)
bundles.UseCdn = true;
BundleTable.EnableOptimizations = true; //force optimization while debugging

var jquery = new ScriptBundle("~/bundles/jquery", "//").Include(
jquery.CdnFallbackExpression = "window.jQuery";

Regardless of how you do it, remember when you setup Pingdom or other availability alerts that you should be testing your Content Delivery Network as well, from multiple locations. In this case, the CDN failure was extremely localized and relatively short but it could have been worse. A fallback technique like this would have allowed sites (like mine) to easily weather the storm.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.