We accidentally changed this behavior from old MVC. This lets us do some pretty useful stuff with constraints so we should bring it back.
Here's an example (old MVC):
routes.MapRoute(
name: "Default_slug",
url: "slug/{controller}/{action}",
defaults: new { controller = "Home", action = "Index", foo = "bar" },
constraints: new { foo = new MyConstraint() });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}}",
defaults: new { controller = "Home", action = "Index" },
constraints: new { foo = new MyConstraint() });
If you navigate to /
then the second route will match, and produces the ambient values:
{ controller = "Home", action = "Index" }
.
Then inside that action, generate a link to another action Url.Action("About")
.
The inputs to link generation:
values: { action = "About" }
ambient values: { controller = "Home", action = "Index" }
When constraints are called, they see the 'accepted values:
{ controller = "Home", action = "About" }
Note that the value foo = "bar"
is not present, even when running the first route's constraints.
Now repeat, but navigate to /slug
to match the first route, producing the ambient values:
{ controller = "Home", action = "Index", foo = "bar" }
.
Generate the same link:
values: { action = "About" }
ambient values: { controller = "Home", action = "Index", foo = "bar" }
When constraints are called, they see the 'accepted values:
{ controller = "Home", action = "About", foo = "bar" }
Note that foo = "bar"
is present because it's an ambient value and not because it's a default value of the route.