ASP.NET MVC Url Helpers: Catalog Your Site
As your site grows, UrlHelpers enable you to keep all links in one location so you don't lose your sanity when a link changes.
You'll notice that having a lot of ActionLinks in your Views is a problem. Why? You were just told you need to changeWhen your site gets large, use a central Use a central location for your URLs
When you build out your site, your list of hyperlinks will grow as well. Hopefully, you aren't using classic ActionLink syntax in your Views which spells trouble.
Why?
I worked with a client who said they needed to change "a couple" urls. The one link they wanted me to change was in every single page. Over 35 pages referred to this link.
Ouch! Ok...lesson learned.
Time to Refactor
In this ASP.NET MVC post, I show you how to take your existing ActionLinks and make it easier to maintain. Because that's what we want in the long run, right?
Url Helpers are primarily extension methods for you to easily create app-specific URLs. Of course, the signature of an extension method is as follows:
- The entire class is static
- The methods are static
- The first parameter in the method signature has a this modifier.
So for our UrlHelper, we have something like this:
Helpers\Url\ThinControllerUrlExtensions.cs
using System.Web.Mvc; namespace ThinController.Helpers.Url { public static class ThinControllerUrlExtensions { public static string RootUrl(this UrlHelper helper) { return helper.RouteUrl("Default"); } } }
In the example, you'll noticed that I'm using the Url.RouteUrl method. When you use the RouteUrl method, you need to pass in a RouteName. These route names are located in your RouteConfig.cs in your App_Start folder.
Why RouteUrl?
I would recommend using the Url.RouteUrl as opposed to any of the other URL generation extension methods.
The four types of links you can build in ASP.NET MVC are:
- Html.ActionLink
Uses HtmlHelpers to generate text with a hyperlink wrapping it (I'll get into HtmlHelpers in a future post). - Html.RouteLink
Uses the Routing collection to find a matching route and create text with a wrapping hyperlink. - Url.Action
Returns a hyperlink as a url string based on a controller, action, and optional id. - Url.RouteUrl
This is by far the fastest way to generate links in your Views. RouteUrl uses the routing collection and returns a hyperlink as a string.
A while back, Chad Moran ran some tests in ASP.NET MVC to see what was the fastest method for generating URLs. The result was Url.RouteUrl (*NOTE* Unfortunately, the page explaining the process and benchmark metrics is not available anymore).
If you need more proof, recently, I created a directory structure (similar to a Yahoo! directory) with a TON of links on a page and was using Html.ActionLink. I noticed the pages taking a long time to render. After reading the post from Chad Moran, he said if at all possible, use Url.RouteUrl. It is the fastest way to generate a link for your site. When I implemented Url.RouteUrl on the page, I noticed a tremendous improvement in rendering speed.
So definitely use it where you can.
What the FAQ?
This UrlHelper class is where you place your application links. I always separate my links into logical "regions" so I can find them later (I can just hear the developers screaming who hate regions).
There are three reasons to always keep this class up-to-date.
- You have a central catalog (or table of contents) for all of your links at a glance.
- You are enforcing the DRY principle in your code.
- IntelliSense is enabled when you include your UrlHelper in your Views.
Let's continue with our FAQ example. We need a FAQ Index, Create, and Update page for your new FAQ module. So your Url Helper class will look like this:
using System.Web.Mvc; namespace ThinController.Helpers.Url { public static class ThinControllerUrlExtensions { public static string RootUrl(this UrlHelper helper) { return helper.RouteUrl("Default"); } public static string FAQUrl(this UrlHelper helper) { return helper.RouteUrl("Default", new { controller="FAQ", action="Index", id = UrlParameter.Optional }); } public static string CreateFAQUrl(this UrlHelper helper) { return helper.RouteUrl("Default", new { controller = "FAQ", action = "Create", id = UrlParameter.Optional }); } public static string UpdateFAQUrl(this UrlHelper helper, string uniqueId) { return helper.RouteUrl("Default", new { controller = "FAQ", action = "Update", id = uniqueId }); } } }
If you want to use these in your Views, your View would look like this:
@using ThinController.Helpers.Url @model ThinController.Models.FaqViewModel <!DOCTYPE html> <html> <head> <title>@Model.PageTitle</title> <meta name="description" content="@Model.MetaDescription" /> <meta name="keywords" content="@Model.MetaKeywords" /> </head> <body> <a href="@Url.RootUrl()" title="Go home">Back to main page</a> <a href="@Url.FAQUrl()" title="Display the list of FAQs">FAQs</a> <a href="@Url.CreateFAQUrl()" title="Create a FAQ">Create a FAQ</a> <a href="@Url.UpdateFAQUrl("5")" title="Update FAQ">Update FAQ number 5</a> </body> </html>
Pretty simple, right?
Now, when you need to change a URL, you just go to your ThinControllerUrlExtensions.cs (or whatever you called it) and change the Url page in your specific UrlHelper route.
Done deal!
Conclusion
UrlHelpers are what I consider to be a Table of Contents or catalog for your application. It gives you an "at-a-glance" view and can probably show you how your application is "logically partitioned" by urls.
I would also like to thank Kazi Manzur for his post about the ASP.NET MVC best practices! I still remember it to this day.
Do you have an interesting UrlHelper trick? Share below in the comments!