Create your own branded url-shortener in under 10 minutes using ASP.NET MVC 2
Jun 10th
Overview
These days, URL shortener services like bit.ly are a dime a dozen. However, the latest craze are branded, shortened URLs like amzn.to instead of amazon.com, nyti.ms instead of nytimes.com, tcrn.ch instead of techcrunch.com, huff.to instead of huffingtonpost.com. You’ve probably seen URLs like these floating around Twitter, Facebook, IM and even email. These abbreviated domains offer the same benefits of a short URL provided by a service like bit.ly (ideal for use on Twitter, etc.) without sacrificing the branded experience and marketing that is achieved by using a “full-size” URL. They are the “compact car” of URLs and they are your friend!
Hence the reason for new services like bitly.Pro. In case your unfamiliar, bitly.Pro is a new service offered by bit.ly that allows companies and individuals to brand their shortened URLs using their own abbreviated domains. Amazon.com already uses http://amzn.to. The New York Times uses http://nyti.ms. Many other companies are using bitly.Pro as well. You may already have your very own abbreviated domain that you’d like to use to brand your shortened urls. If not, go get one. So, like me, you figure you’ll head on over to http://bitly.pro/signup to sign up for the free beta only to find out that the beta is closed to new users at this time. (Update: bitly.Pro beta has re-opened and you can signup here: http://bit.ly/a/pro_request).
But wait…before you begin cursing bit.ly about their closed beta, allow me to present a quick solution that still allows you to brand your shortened links and track traffic to your branded service. It won’t give you the analytics regarding how your content is begin distributed across Twitter, Facebook, etc. (although you could build that in fairly easily), but for someone who just wants a simple branded url shortener solution, it will fit the bill.
So, without further ado, here’s the simple ASP.NET MVC-based solution that provides a simple bitly.Pro-like solution of your very own. Best of all, you can get it going in under 10 minutes. Of course, you could build the same solution entirely with javascript and an html page, but where’s the fun in that?
Getting Started
The easiest way to get started is to head over to http://www.asp.net/ and use the Web Platform Installer to install Visual Web Developer 2010 and ASP.NET MVC 2.
Once you’ve got these installed, fire up VS2010 and add a new “ASP.NET MVC2 Empty Web Application.”
You should end up with something that looks like this:
The Controller
The first thing we want to do is setup a controller to handle our requests, so right-click the Controllers directory in the Solution Explorer and select Add > Controller.
We’ll name ours “HomeController” and, since we won’t be doing anything with an actual model, we’ll leave the box unchecked that prompts us to create actions methods for Create, Update and Delete scenarios.
Our HomeController is going to be very simple and will look like this:
using System.Web.Mvc;
namespace bitlyProSimple.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResult Index(string linkid)
{
Response.StatusCode = 302;
Response.RedirectLocation = (string.IsNullOrWhiteSpace(linkid)
? "http://anderly.com"
: string.Format("http://bit.ly/{0}", linkid));
return new ContentResult();
}
}
}
Our controller is going to accept a string (the linkid) and then contstruct a 302 redirect to bit.ly to finish the job. This allows us to simply use the bit.ly analytics when you have a bit.ly account.
As you can see, we are using bit.ly, but you could very well use any other URL shortener service. Essentially, what we’ll be doing is mapping requests that match the format http://[yourdomain]/[linkid] to our HomeController which will accept the linkid as a parameter and then prepare to forward our request to bit.ly. So in my case, my abbreviated domain is http://ander.ly. So, I’ll be mapping any requests that match the http://ander.ly/[linkid] format to be forwarded to http://bit.ly/[linkid].
In case there isn’t a link id, we will simply redirect to the blog home page.
Wrapping Up
Last but not least, we need to head on over to Global.asax.cs to setup our Routes and we’ll be done.
Open up Global.asax.cs and replace the default route of:
{controller}/{action}/{id}
with
{linkid}
That’s it!
Fire up the solution and test it out for yourself. Don’t forget to bookmark the location of this post: http://ander.ly/bGSr9K
Now any requests that come in that match the format http://ander.ly/[linkid] will be sent to our HomeController which will extract the linkid and construct a new bit.ly URL of the same format and do a simple redirect for the user.
With this solution, we can simply use the existing bit.ly URL shortener service without having to roll our own and we can simply replace bit.ly in any shortened URLs with our very own branded abbreviated domain.
Now you too can start branding the links you share.
Let the shameless self-promotion begin!
Source Code
Silverlight MobileMe Gallery now on CodePlex!
Nov 24th
I have published the initial source for my project “Recreating the MobileMe Gallery in Silverlight 3” on CodePlex.
You can now access the Alpha release of the code here: http://silverlightmobileme.codeplex.com/
I will be updating I have updated the working example (http://gallery.restazured.com/emily_parker) as well to reflect the latest version on CodePlex.
Please leave your comments and let me know if you have any questions…or if you would like to be a contributor to the project.
Enjoy!
Recreating the MobileMe Gallery in Silverlight 3 – Part 1
Oct 21st
In my introductory post I detailed the features needed to successfully recreate the MobileMe Gallery in Silverlight 3. While a bit late, this is Part 1 of a multi-part series where I will detail out step-by-step the process of Recreating the MobileMe Gallery in Silverlight 3.
The Tools
I will assume you already know what tools are required to do Silverlight development. If not, go here: http://timheuer.com/blog/articles/silverlight-get-started-part-1-hello-world.aspx
For this post, you will also need a tool such as Fiddler or Web Development Helper in order to do some HTTP tracing.
Getting Started
For this post we are going to focus on the initial plumbing required to retrieve the data from the MobileMe Gallery. The first thing we’ll need is the underlying data (album definitions, etc.) stored on the MobileMe site so that we can populate our Silverlight Gallery. To do so, we’ll need to see what the Apple MobileMe Gallery does under the covers.
So, if you head over to the MobileMe Sample Gallery you should see the following:
In order to find out if the underlying album data is accessible, I’m going to use the Web Development Helper IE Add-In to do some HTTP Tracing on the Apple MobileMe Gallery. After firing up Web Development Helper and turning on HTTP logging (HTTP > Enable HTTP Logging), I can then refresh the browser and should see a long list of HTTP requests in the console like so:
If you scroll up in the list, you should find the entry highlighted above. This is the main request we are concerned with. Double-clicking on this request and then selecting the “Reponse Content” tab at the bottom provides more details.
There you have it! A good ‘ol fashion HTTP GET request returning JSON. A quick glance over this data shows you that this JSON response contains the gallery details we’re after. So far, so good.
Getting the Data
Now we know where to get the data, but how do we get it? You may say just use the WebClient class in Silverlight to do an HTTP GET request. However, Silverlight requires client access policy files for cross-domain HTTP requests in order to provide a security mechanism to service authors to specify who can and cannot access their services. There are some public web services that already have these files in place for Flash, but Silverlight requires its own flavor. Additionally, the Apple MobileMe Gallery doesn’t have one. Therefore, we need our own service (WCF service that-is) that will serve as a proxy between the Apple MobileMe Gallery service and our Silverlight MobileMe Gallery client. In short, we’ll call our WCF service (that we’ll author) and our service will call the Apple MobileMe Gallery service. This is a common workaround as the Silverlight client performs the check for the client access policy file while WCF doesn’t do any checks because it’s a server technology.
Writing our Service
We’ll start off by creating an empty Visual Studio Solution called Gallery. Then, we’ll add a new “WCF Service Application” project to the solution – giving it the name Gallery.Service. Here is the structure of the service project after being built out.

IGallery.cs is our service contract that will define the signatures for the methods we’ll need to call to retrieve gallery and album details. It looks like this:

IPolicyProvider.cs is our policy provider contract that will define the signature for the method that will return the Silverlight client access policy file. It looks like this:

As you’ll notice, both of these interfaces are using the WebGet attribute to map specific UriTemplates to these service methods. For instance, in IPolicyProvider, we are saying if an HTTP GET request comes in to our root service folder followed by “/clientaccesspolicy.xml,” then that means run this method. We do this because anytime a Silverlight client makes any cross-domain request, it first makes a request to “clientaccesspolicy.xml” to see if it has rights to access the service.
Finally, our implementation of Gallery.svc.cs looks like this:
Here, you’ll notice that our GetGallery and GetAlbum methods are simply using WebClient to call the gallery service and album service using url formats defined in Web.config. These are:
You’ll notice that the first entry (PhotocastUrlFormat) is the same format as the HTTP request we observed using Web Development Helper. And we simply, leave a curly-brace placeholder for the MobileMe username which we’ll substitute at run-time.
Minus WCF configuration settings which are included in the source, we now have a working service which will forward calls to the Apple MobileMe service to retrieve gallery and album details. This service is currently available at http://igallery.restazured.com/GalleryService.svc
Feel free to wire up your WCF client of choice (Silverlight, WPF, etc.) add a service reference and try calling one of the methods passing your own MobileMe username or the sample “emily_parker”. You can even see the client policy provider in action here: http://igallery.restazured.com/clientaccesspolicy.xml
Wrapping Up
Now, we have a WCF service setup to forward our requests for MobileMe Gallery and Album details to the Apple MobileMe Service. In Part 2, we’ll start creating the Silverlight project to call our WCF service and start building the home page to look like: http://gallery.me.com/emily_parker
In the meantime, checkout the working example (using Silverlight 3) here: http://gallery.restazured.com/emily_parker
Silverlight Midpoint Rounding Solution
Aug 8th
As a follow up to my previous Shakespearean-titled post on rounding, I decided to provide a quick follow up to provide a solution for midpoint rounding in Silverlight. Based on some traffic that I’ve been getting it looks like people are searching for a rounding solution in Silverlight since the Silverlight core framework lacks the traditional Math.Round() overloads we get with the full .NET framework that allow specifying the desired midpoint rounding behavior.
Remember, Silverlight contains a pared-down version of the .NET framework.
So, here is a simple solution to take what we learned in the previous post and develop our own MathExt helper class that provides static Round methods similar to the Math.Round() methods that allow us to specify the desired midpoint rounding behavior. Using this you can now control midpoint rounding behavior in Silverlight.
public enum MidpointRounding
{
ToEven,
AwayFromZero
}
public static class MathExt
{
public static decimal Round(decimal d, MidpointRounding mode)
{
return MathExt.Round(d, 0, mode);
}
/// <summary>
/// Rounds using arithmetic (5 rounds up) symmetrical (up is away from zero) rounding
/// </summary>
/// <param name="d">A Decimal number to be rounded.</param>
/// <param name="decimals">The number of significant fractional digits (precision) in the return value.</param>
/// <returns>The number nearest d with precision equal to decimals. If d is halfway between two numbers, then the nearest whole number away from zero is returned.</returns>
public static decimal Round(decimal d, int decimals, MidpointRounding mode)
{
if (mode == MidpointRounding.ToEven)
{
return decimal.Round(d, decimals);
}
else
{
decimal factor = Convert.ToDecimal(Math.Pow(10, decimals));
int sign = Math.Sign(d);
return Decimal.Truncate(d * factor + 0.5m * sign) / factor;
}
}
}
Or if you prefer an extension-method approach:
public enum MidpointRounding
{
ToEven,
AwayFromZero
}
public static class DecimalExtensions
{
public static decimal Round(this decimal d, MidpointRounding mode)
{
return d.Round(0, mode);
}
/// <summary>
/// Rounds using arithmetic (5 rounds up) symmetrical (up is away from zero) rounding
/// </summary>
/// <param name="d">A Decimal number to be rounded.</param>
/// <param name="decimals">The number of significant fractional digits (precision) in the return value.</param>
/// <returns>The number nearest d with precision equal to decimals. If d is halfway between two numbers, then the nearest whole number away from zero is returned.</returns>
public static decimal Round(this decimal d, int decimals, MidpointRounding mode)
{
if (mode == MidpointRounding.ToEven)
{
return decimal.Round(d, decimals);
}
else
{
decimal factor = Convert.ToDecimal(Math.Pow(10, decimals));
int sign = Math.Sign(d);
return Decimal.Truncate(d * factor + 0.5m * sign) / factor;
}
}
}
Remember, the non-extension-method version could easily be used in any legacy .NET projects that still may be on 1.0 or 1.1 to give us the ability to control midpoint rounding behavior which didn’t arrive in the framework until .NET 2.0.
Once again, Happy Rounding!
To round ‘up’, or to round ‘down’: that is the question
Jul 28th
In troubleshooting a rounding discrepancy a couple of years ago in a software component, I discovered what may be a lesser known fact – the Microsoft programming languages (VBScript, VBA, VB6, VB.NET, C#, etc.) implement what is commonly referred to as “banker’s rounding” or “rounding to the nearest” – which follows the IEEE Standard 754, section 4. My reason for posting about this is that in some cases, this can yield unexpected results.
As we all know, traditional arithmetic rounding (the kind we all learned in grade school) says .5 always rounds up. However, the IEEE Standard 754, section 4 does not implement this form of symmetrical arithmetic rounding.
Here’s the explanation:
Given the range 0 – 1
[.1 .2 .3 .4] – always rounds down
[.6 .7 .8 .9] – always rounds up
However, .5 is the midpoint between 0 and 1 and always rounding .5 in the same direction results in a bias that grows with the more numbers you add together.
So, the IEEE Standard says that one way to minimize the bias is with “banker’s rounding” which is as follows:
Banker’s rounding rounds .5 up sometimes…and down sometimes. The convention is to round to the nearest even number, so that both 1.5 and 2.5 round to 2, and 3.5 and 4.5 both round to 4. Banker’s rounding is symmetric.
Here are a few sample results using the IEEE Standard (banker’s rounding):
Value |
Rounded to 2 Decimal Places |
| 0.1250 | 0.12 (Rounds down when the number to the left of the 5 is even) |
| 0.1350 | 0.14 (Rounds up when the number to the left of the 5 is odd) |
| 0.1251 | 0.13 (Rounds up because the 1 to the right of the 5 since it is not exactly the midpoint between .12 and .13) |
| 0.125000001 | 0.13 (Rounds up for the same reason as the one above) |
|
|
You may already be aware of this seemingly odd behavior, but many of you may be surprised by this result (as I was).
In any case, I wanted to share my findings in case you were expecting a rounding implementation different than that which is actually implemented in the products/programming languages you are using.
Microsoft acknowledges that their rounding implementation is inconsistent across products (VBScript, VBA, VB6, .NET, SQL Server, EXCEL) and says that this is only done for historical reasons. Here is the link to the Microsoft KB article that details the different rounding implementations in their products and how to implement a custom rounding method based on your need: http://support.microsoft.com/?kbid=196652
Here’s the breakdown of the rounding implementations for Microsoft Products:
| Product | Implementation |
| VBScript, VBA, VB 6.0 | Banker’s Rounding |
| Excel Worksheet | Symmetric Arithmetic Rounding |
| SQL Server | Either Symmetric Arithmetic Rounding or Symmetric Round Down (Fix) depending on arguments |
| .NET 1.0, 1.1 | Banker’s Rounding |
| .NET 2.0 (or greater) | Banker’s Rounding but provides additional overloads to the Math.Round() method for specifying desired midpoint rounding behavior. |
So, the good news is that if you are using SQL Server or Excel rounding, you are fine – you’re gonna get good ‘ol traditional arithmetic rounding (.5 always rounds up).
Also of interest, is that the Java Math library (including JavaScript) implements Asymmetric Arithmetic Rounding.
The key difference between this and Symmetric Arithmetic Rounding (the kind we learned in grade school) is as follows:
Symmetric Arithmetic Rounding always rounds up, where “up” is defined as “away from zero.”
So, 0.1250 rounds to 0.13 and -0.1250 rounds to -0.13.
Asymmetric Arithmetic Rounding always rounds up, where “up” is defined as “heading towards positive infinity.”
So, 0.1250 rounds to 0.13 and -0.1250 rounds to -0.12 (i.e. in a positive direction).
As for my case, I wanted Symmetric Arithmetic Rounding and followed the instructions in the KB article above for implementing my own custom Round method to achieve this result.
Here is the final implementation:
/// <summary>
/// Implements alternate rounding methods, in contrast to Decimal.Round()
/// and Math.Round(), which implement banker's rounding (5 rounds to even).
/// See http://support.microsoft.com/?kbid=196652 for other methods.
/// </summary>
public static class MathExt
{
/// <summary>
/// Rounds using arithmetic (5 rounds up) symmetrical (up is away from zero) rounding
/// </summary>
/// <param name="d">d: A System.Decimal number to be rounded.</param>
/// <param name="decimals">The number of significant fractional digits (precision) in the return value.</param>
/// <returns>The number nearest d with precision equal to decimals. If d is halfway between two numbers, then the nearest whole number away from zero is returned.</returns>
public static decimal Round(decimal d, int decimals)
{
decimal factor = Convert.ToDecimal(Math.Pow(10, decimals));
int sign = Math.Sign(d);
return Decimal.Truncate(d * factor + 0.5m * sign) / factor;
}
}
I would encourage you to review any rounding code in your apps and verify that the rounding implementation is the one you expected.
Happy Rounding!









Recent Comments