Last updated .
In MVC, there is no direct correspondance between a request (URL) and a file on disc. Instead, requests are routed to controller classes that process the request. You may recall that such public methods of controller classes that handle a request are termed "action" methods. The MVC routing serves two purposes:
Routing works by matching parts of URL with one or more patterns. This pattern matching is only concerned with the part of the URL that is not the servername or query string. This part of the URL constitutes a path that consists of segments, separated by '/', for example:
http://myserver.com:7001/consulting/mvc/search?iq=high
In this example, there are three segments, namely "consulting", "mvc" and "search". These are the parts of the URL that are considered in routing. However, in addition to the mapping of a URL to a controller class, routing also has a job on the side of fetching parameters from the query string, which are then passed to action methods.
The routing scheme is configured by registering one or more routes. When a request comes in, the MVC framework enumerates the configured routes and uses the first
one that matches. This means that it matters in what order the routes are registered. Generally, register the most specific patterns first and the most general ones last.
In more technical terms, the routes are configured in the
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
This code declares a route, which has a name of "default" and a template property. The template is the pattern that the URL of an incoming request is matched with. This particular route matches a URL with three segments, of which the last one is optional, as indicated by the '?' suffix. The segments are named "controller", "action" and "id", respectively. The first two are set up with default values, which will be used, if that segment is missing from the url. Note that words such as "controller" or "action" have no special meaning in relation to routing per se. They only acquire special meaning after a route has been matched and then used by the MVC framework to find a controller to call. The above route will match URLs such as:
http://myserver.com/segment1/segment2/segment3
http://myserver.com/segment1/segment2
http://myserver.com/segment1?id=somevalue
A URL with more than three segments would not be matched.
As shown above, you can define a named variable for a segment, but it's also possible to assign a constant value to a segment or part of a segment. For example the template
"admin/{controller}/{action}"
will match URL's of precisely three segments, of which the first one
must be "admin". As another example, consider the template
"admin{controller}/{action}"
. It will match URLs consisting of two segments, where the first segment starts with "admin".
So, the URL http://myserver.com/adminhome/index
is a match for the template and the value of the resulting route's
Instead of defining default values for .../Home/...
URL. You can then insert a route as the first one that catches that situation:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "OldHome",
template: "Home/{action}",
defaults: new { controller = "NewHome" });
routes.MapRoute(
name: "default",
template: "{controller=NewHome}/{action=Index}/{id?}");
});
With these two routes, users requesting a URL such as .../Home/Index
would actually be served by the new
In addition to the built-in
Views/Shared/Route.cshtml
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
@model Microsoft.AspNet.Routing.RouteData
<!doctype html>
<html>
<head>
<title>RouteData</title>
</head>
<body>
<h2>RouteData:</h2>
<ul>
@foreach (var key in Model.Values.Keys) {
<li><strong>@key</strong>: @Model.Values[key]</li>
}
</ul>
</body>
</html>
The very simple controller renders the view, passing on the
Controllers/RouteController.cs
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
using Microsoft.AspNet.Mvc;
namespace MVCTutorial.Controllers
{
public class RouteController : Controller
{
public IActionResult Index()
{
return View("Route", RouteData);
}
}
}
The
Startup.cs (partial)
1:
2:
3:
4:
5:
.....
routes.MapRoute(
name: "default",
template: "{controller=Route}/{action=Index}/{someParam?}/{otherParam?}");
.....
The contents of
The
Controllers/RouteController.cs (partial)
1:
2:
3:
4:
5:
6:
7:
.....
public IActionResult Index(decimal someParam)
{
ViewData["someParam"] = someParam;
return View("Route", RouteData.);
}
.....
The view now displays the value of the parameter, fetched from the
Views/Shared/Route.cshtml (partial)
1:
2:
3:
4:
5:
6:
7:
8:
9:
.....
<h2>RouteData:</h2>
someParam: @ViewData["someParam"]
<ul>
@foreach (var key in Model.Values.Keys) {
<li><strong>@key</strong>: @Model.Values[key]</li>
}
</ul>
.....
Requesting localhost[port]
shows that the localhost[port]/route/index/17.9
makes the value acquire the value 17.9. The parameter can also be passed as
a query string parameter, as the third screen shot shows:
If the same value is passed in a URL segment and in the query string, the segment wins.
2016 by Niels Hede Pedersen