views:

203

answers:

2

I have two routing rules in an ASP.NET MVC application :

            routes.MapRoute(
               "Products AJAX",
               "Products/Ajax/{action}",
               new { controller = "Products" }
            );

            routes.MapRoute(
               "Product",                                             
               "Products/{id}",                                        
               new { controller = "Products", action = "ViewProduct", id = "1001" }  
            );

The second rule here allows me to create a url /Products/1002 to view product 1002. This is the original sole rule I created.

I wanted to add some AJAX on the view to allow it to retrieve a simple string :

 public class ProductsController : Controller {
    public ContentResult GetStatus()
        {
            return new ContentResult()
            {
                Content = "Status is OK at " + DateTime.Now.ToLongTimeString()
            };
        }
  }

This is why I added the first routing rule above. I wanted it to be a more specific URL that could be used to go to any other actions defined within my controller. (If I didnt have this rule it would attempt to find a product with the SKU of 'GetStatus' which is no good!)

So I thought ok thats fine, I just need to write my AJAX command in my view as :

<%= Ajax.ActionLink("Update Status", "AJAX/GetStatus", new AjaxOptions { UpdateTargetId = "status" })%>

I assumed this would call the link Products/AJAX/GetStatus, which would trigger the first routing rule and correctly go to my controller's GetStatus method.

To my surprise the URL when I hover over this command in internet explorer (or view source) becomes /Products/AJAX/AJAX/GetStatus.

So I'm thinking whaaat, and I backtrack to perform some detective work.

I change my first rule to :

MapRoute(
               "Products AJAX",
               "Products/Foo/{action}",
               new { controller = "Products" }
            );

and I change my action to

<%= Ajax.ActionLink("Update Status", "GetStatus", new AjaxOptions { UpdateTargetId = "status" })%>

To my amazement the URL generated for this ActionLink is actually /Products/Foo/GetStatus. This based on my first rule correctly forwards to my AJAX handler and everything works great. And of course a link of /Products/1003 would match the second rule and go to product 1003.

My application is complete! I'm happy - sort of.

But I don't know why! The ONLY place in my whole codebase where I have Foo is in my mapping rule so how on earth is the Ajax.ActionLink able to figure out that I want that link?

Evidently there is some kind of 'clever' reverse mapping being done. I cant seem to find any documentation about this and would like to know more.

I think it must be parsing the FIRST rule it finds or something like that, but it seems a little scary since I like to know whats going on.

Note: There is a very nice article about routing - including generation of URLs from the routing table on ScottGu's blog. Unfortunately I coudlnt seem find an explanation of whats going on in my situation in that blog.

A: 

Yes, that's the point of the ActionLink helper and the routing - if you change your entire routing structure, you only have to update it in one place, and ActionLinks continue to generate correct URLs.

To elaborate a bit further, when you're using the ActionLink helper, you're essentially saying to the system "Link to the Controller and Action, I don't care how that's done"

Damien_The_Unbeliever
The question was exactly that : HOW ? I mean he can see by himself that it works. He wants to know the how :). I guess he could use Reflector but that's not exactly an explanation.
sirrocco
I thought it was worth mentioning though, since his first code sample seemed to be thinking "I need to provide the route here"
Damien_The_Unbeliever
ActionLink code sample (3rd in total)
Damien_The_Unbeliever
+1  A: 

Since you have a named route, why not use it? Use Ajax.RouteLink, instead, and specify the route name. Then you do not have to worry about ASP.NET "guessing" the wrong route. It won't hurt anything that this is faster, too.

Craig Stuntz
thanks - i wasnt aware i could do that. the MS tutorials on AJAX seem to be lacking and i've just been reading about it from random places.
Simon_Weaver
do you happen to know its heuristic? is it just picking the FIRST routing rule and trying to stick its parameters into that?
Simon_Weaver
It picks the first match. See:http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx
Craig Stuntz