ASP.Net MVC Outgoing Routing ActionLink mismatch
 
We recently experienced an unexpected problem when attempting to re-route obsolete URLs using ASP.Net’s MVC routing mechanism.  The scenario was that we had been running a competition, and had a set of URLs associated with it in the format http://server/Competition/etc.  We now needed to re-route all incoming requests to these pages back to the site’s home page.  In order to achieve this, we added the following to the routing table:
 
routes.MapRoute(
   null,
   "Competition/{action}/{id}",
   new { controller = "Home", action = "Index", id = "" }
   );

 

In the majority of cases this worked fine.  However, a handful of links unrelated to the competition now exhibited strange behaviour.  For example, the menu item on the home page that was a link to itself (i.e. the home page) now had the URL http://server/Competition rather than http://server/.  The link itself was generated in the view Home/Index.aspx using an ActionLink:

<%= Html.ActionLink("Home", "Index", "Home")%>

 

It turned out that the problem was with self-referencing ActionLinks where the link matched the controller and action for the given view.  The outgoing URLs for these self-referencing ActionLinks now matched the new competition route.  The problem was resolved by adding a constraint to the route, ensuring that this route was only applied to incoming requests:

routes.MapRoute(
   null,
   "Competition/{action}/{id}",
   new { controller = "Home", action = "Index", id = "" },
   new { routeDirection = new IncomingRequestConstraint() }
);

 

The new constraint, IncomingRequestConstraint, checks the route direction:

public class IncomingRequestConstraint : IRouteConstraint
{
   public bool Match(System.Web.HttpContextBase httpContext, 
      Route route, 
      string parameterName, 
      RouteValueDictionary values, 
      RouteDirection routeDirection)
   {
      return routeDirection == RouteDirection.IncomingRequest;
   }
}

 

Post Script: Legacy URLs

The above example is a slightly simplified version of how we dealt with the obsolete URLs.  In order to establish that the re-routing was permanent and use an HTTP 301 redirect, we made use of the legacy URL routing described by Matt Hawley at eXcentrics World.  Our actual route looked like this:

routes.Add(
   null,
   new LegacyRoute
   (
      "Competition/{action}/{id}",
      "RedirectHome",
      new LegacyRouteHandler()
   )
);

 

As a result, the same outgoing URL now took the form http://server/Competition/Index/?controller=Home.  Adding the constraint resulted in:

 

routes.Add(
   null,
   new LegacyRoute
   (
      "Competition/{action}/{id}",
      "RedirectHome",
      new LegacyRouteHandler()
   )
   {
      Constraints = new RouteValueDictionary(
         new { routeDirection = new IncomingRequestConstraint() }
         )
   }
);

Comments

# <br /> ASP.NET MVC Archived Blog Posts, Page 1<br />
Gravatar <br /> ASP.NET MVC Archived Blog Posts, Page 1<br />
Left by Pingback/TrackBack on 1/11/2010 5:19 PM

Leave Your Comment

Title*
Name*
Email (never displayed)
 (will show your gravatar)
Url
Comment*

Please add 4 and 4 and type the answer here:

Preview Your Comment.