» Client-side routing with ASP.NET MVC - Geek Stuff
Subscribe

Client-side routing with ASP.NET MVC

While working with ASP.NET MVC on the last two years I’ve found lots of people on StackOverflow asking how to build urls on a javascript file. In most cases, this is needed when fetching data from the server using AJAX.

The top answers to this questions were:

  1. Store the url in a javascript variable in the header and use it in your javascript file.
  2. Store the url in a hidden input and use jQuery to get it.
  3. Hardcode the url. Eg.: $.getJSON(‘/Users/List’, …)

All of them works, but I tried to do something different and have come to a very clean way to build the urls.

Example

Let’s suppose we have a route defined like this:

routes.AddRoute(
    "Login",
    "login",
    new { controller = "Login", action = "Index" }
);

To get that url in javascript you only need to do this:

var url = Url.Route("Login"); //Where Login is the name of the route

Looks like C#, but it’s not. That was easy, no parameters and pretty straightforward route format. But when you have something like this:

routes.AddRoute(
    "ProductDetails",
    "product/{id}/details",
    new { controller = "Product", action = "Details", id = 100 }
);

Which is not a complex route, but it’s very common, the javascript code will look like:

var url = Url.Route("ProductDetails", {id: 2});

Awesome, don’t you think? I like it :)

Behind the Scenes

This solutions works similar to my last post, there is a custom HttpHandler that is outputting all routes configuration as javascript objects and the Url is an interface to use all those routes.

To use it just add these two references to your masterpage:

<script src="@Url.Content("~/Scripts/mvcroute.js")" type="text/javascript"></script>
<script src="@Url.Content("~/routelist.axd")" type="text/javascript"></script>

The routelist.axd is a custom HttpHandler and must be defined in the web.config:

<system.web>
  <httpHandlers>
    <add path="routelist.axd" verb="GET" type="JsMvcRouting.RouteListHandler, JsMvcRouting" />      
  </httpHandlers>
</system.web>

Remember to use the custom AddRoute extension method instead of the MapRoute when creating your routes. The only difference is that this method add the route name to the datatokens so we can get it back later.

Tip #1: Adding cache to the HttpHandler is safe and would boost the performance since the routes don’t change in runtime (at least on most projects).

Tip #2: For those routes that you find yourself using all the time, you can add a shortcut to it like this:

//Create the shortcut
Url.Login = function () {
    return this.Route("Login");
}
 
//Use it
url = Url.Login();

The source code of a running web application with all these examples is available here.

4231042accf857d06dea56861f698a27

Related posts:

  1. Subdomain Routing on ASP.NET MVC
Tagged , ,

4 thoughts on “Client-side routing with ASP.NET MVC

  1. DotNetWise says:

    What about a nuGet package for the thing?

    • goenning says:

      That would be nice, but I think it does need to grow a little before becoming a package. I’ve created a dedicated GitHub repository for it. Let’s see if we can make it better and then publish it as a NuGet package.

  2. Will says:

    Ran into an issue when trying to use this package on my local site. It first conflicted with the out of the box setup you get with your MVC 3 internet template telling me there was a resolution error trying to resolve the Controllers/Home so to resolve that issue I provided a default namespace. That resolved that issue but then when I attempted to grab the default route with Url.Route(“Default”) just like in the sample provided in the Index view it fails and I get an error stating that it can not found the “Default” route. Not sure what I am doing wrong

    • goenning says:

      Hello Will.

      It’s hard to say what is the problem without looking at the source code. But I think that the first problem is that you have compiled my JsMvcRouting prject and added it as a reference to your project. Is that right? I think this is why you got a conflict with the HomeController.

      I’ve created a new internet mvc3 application from scratch, added the necessary files, made the configurations described in this post and it worked as expected.

      I’ve uploaded the result, take a look: http://geekstuff.cc/wp-content/uploads/downloads/2012/01/internet-template-mvc3-client-side-routing.zip

      Hope it works.

      By the way, as said in my last comment, I am planning to deliver it as a NuGet package, but I need to do some changes before.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">