static void

ASP Routing

MSDN, Asp.Net. For debugging, Install-Package routedebugger

In .net 4+ with a Microsoft IIS patch will make routing work, but otherwise you may have to set runAllManagedModulesForAllRequests (NB: this may mean static .css and .js are authenticated, and the login page becomes a little plain!).

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true" />

In Webforms

See MSDN

In MVC

Routes are defined in from global.asax Application_start: RegisterRoutes(RouteTable.Routes);

Mvc uses the route conventions of {controller} and {action}, with defaults as required.

routes.MapRoute(
    "Yearly",
    "{year}/{controller}/{action}/{id}",
    new { year = DateTime.Now.Year, controller = "Home", action = "IndexByYear", id = UrlParameter.Optional }
);

...will map http://site/1983/Products/display/123 to ProductsController (implementing IController) method Display, passing in parameter with name id=123 and year with default 2010.

Route Defaults and Constraints

routes.MapRoute(
    "Yearly",
    "{year}/{controller}/{action}/{id}",
    new { year = DateTime.Now.Year, controller = "Home", action = "IndexByYear", id = UrlParameter.Optional },
    new { year = @"\d{4}" });

Default/ 404 routes

Remember this should always be the last route.

routes.MapRoute("Error",
    "{*url}",
    new { controller = "Error", action = "404" }
);

*Catchalls

//mydomain/Product/Index/A/Extra/More will invoke action
// public ActionResult Index(string id, string catchall)
// id = "A" and catchall = "Extra/More".
routes.MapRoute("MyCatchallRoute",
    "{controller}/{action}/{id}/{*catchall}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional });

Duplicate controller names

If you have two "HomeControllers" in different namespaces you have a YSOD error. So add two routes and specify the namespaces (the namespace string array is not a hierarchy)

routes.MapRoute("MyRoute", "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    new[] { "MyPriorityNamespace.Controllers" });
 

To stop searches (first match only)

//To stop searching all namespaces
myRoute.DataTokens["UseNamespaceFallback"] = false;
 

In controllers

Controllers have a RedirectToAction() method.

In Views

use Html.ActionLink or Html.RouteLink

<li><a href="/Home/About">Go to About (manual link)</a></li>

<li><a href="@Url.ActionLink("About", "Home")">Go to About (URL link)</a></li>

ActionLinks

<li>@Html.ActionLink("Go to About", "About")</li>
<li>In another controller</li>
<li>@Html.ActionLink("Go to LogOn", "LogOn", "Account")</li>
<li>Below renders as /Home/Details/2 . The final null is important otherwise you get /Home/Details?Length=4</li>
<li>@Html.ActionLink("Go to Details with parameter", "Details", "Home", new { id = 2 }, null)</li>

RouteLinks

<li>@Html.RouteLink("Go to Logon", new { controller = "Account", action = "Logon" })</li>
<li>@Html.RouteLink("Use named route","SpecialRoute")</li>
<li>Areas</li>
<li>@Html.ActionLink("Go to Admin area", "Index", "User", new { area = "Admin" }, null)</li>

WebAPI

WebApi routes in javascript (assuming default route name)

var url = '@Url.HttpRouteUrl("DefaultApi", new { controller="Data"} )';

WebApi routes via html anchor (assuming default route name). Note the "httproute=true".

<p>@Html.RouteLink("Call my api", "DefaultApi", new { controller = "Values", httproute= true, id = 1 }, new { @class = "btn btn-info" }).</p>

Areas

AreaRegistration happens before other routes, so the areaName (first part) is matched before the other routes. Remember for actions to areas to specify the area (or "" for top level).

@Html.ActionLink("Go to Admin area", "Index", "User", new { area = "Admin" }, null)
@Html.ActionLink("Go to Home", "Index", "Home", new { area = "" }, null)