Skip to content

Commit 5c5d924

Browse files
catch-all routing bug (#18121)
* catch-all routing bug * catch-all routing bug * catch-all routing bug * catch-all routing bug * catch-all routing bug
1 parent 9e62c03 commit 5c5d924

4 files changed

Lines changed: 29 additions & 2 deletions

File tree

aspnetcore/fundamentals/routing.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ The details of how precedence works are coupled to how route templates are defin
343343
* A segment with literal text is considered more specific than a parameter segment.
344344
* A parameter segment with a constraint is considered more specific than one without.
345345
* A complex segment is considered as specific as a parameter segment with a constraint.
346-
* Catch all parameters are the least specific.
346+
* Catch-all parameters are the least specific. See **catch-all** in the [Route template reference](#rtr) for important information on catch-all routes.
347347

348348
See the [source code on GitHub](https://github.com/dotnet/aspnetcore/blob/master/src/Http/Routing/src/Template/RoutePrecedence.cs#L189) for a reference of exact values.
349349

@@ -411,6 +411,8 @@ Asterisk `*` or double asterisk `**`:
411411
* Matches any URI that starts with `/blog` and has any value following it.
412412
* The value following `/blog` is assigned to the [slug](https://developer.mozilla.org/docs/Glossary/Slug) route value.
413413

414+
[!INCLUDE[](~/includes/catchall.md)]
415+
414416
Catch-all parameters can also match the empty string.
415417

416418
The catch-all parameter escapes the appropriate characters when the route is used to generate a URL, including path separator `/` characters. For example, the route `foo/{*path}` with route values `{ path = "my/path" }` generates `foo/my%2Fpath`. Note the escaped forward slash. To round-trip path separator characters, use the `**` route parameter prefix. The route `foo/{**path}` with `{ path = "my/path" }` generates `foo/my/path`.

aspnetcore/includes/catchall.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
> [!WARNING]
2+
> A **catch-all** parameter may match routes incorrectly due to a [bug](https://github.com/dotnet/aspnetcore/issues/18677) in routing. Apps impacted by this bug have the following characteristics:
3+
>
4+
> * A catch-all route, for example, `{**slug}"`
5+
> * The catch-all route fails to match requests it should match.
6+
> * Removing other routes makes catch-all route start working.
7+
>
8+
> See GitHub bugs [18677](https://github.com/dotnet/aspnetcore/issues/18677) and [16579](https://github.com/dotnet/aspnetcore/issues/16579) for example cases that hit this bug.
9+
>
10+
> An opt-in fix for this bug is planned. This doc will be updated when the patch is released. When the patch is released, the following code will set an internal switch that fixes this bug:
11+
>
12+
>```
13+
>public static void Main(string[] args)
14+
>{
15+
> AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior", true);
16+
> CreateHostBuilder(args).Build().Run();
17+
>}
18+
>// Remaining code removed for brevity.
19+
>```

aspnetcore/migration/22-to-30.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,10 @@ Review breaking changes:
12171217
* [Breaking API changes in Antiforgery, CORS, Diagnostics, MVC, and Routing](https://github.com/aspnet/Announcements/issues/387). This list includes breaking changes for compatibility switches.
12181218
* For a summary of 2.2-to-3.0 breaking changes across .NET Core, ASP.NET Core, and Entity Framework Core, see [Breaking changes for migration from version 2.2 to 3.0](/dotnet/core/compatibility/2.2-3.0).
12191219

1220+
## Endpoint routing with catch-all parameter
1221+
1222+
[!INCLUDE[](~/includes/catchall.md)]
1223+
12201224
## .NET Core 3.0 on Azure App Service
12211225

12221226
The rollout of .NET Core to Azure App Service is finished. .NET Core 3.0 is available in all Azure App Service datacenters.

aspnetcore/mvc/controllers/routing.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,9 @@ The preceding example:
190190
### Conventional routing order
191191

192192
Conventional routing only matches a combination of action and controller that are defined by the app. This is intended to simplify cases where conventional routes overlap.
193-
Adding routes using <xref:Microsoft.AspNetCore.Builder.ControllerEndpointRouteBuilderExtensions.MapControllerRoute*>, <xref:Microsoft.AspNetCore.Builder.ControllerEndpointRouteBuilderExtensions.MapDefaultControllerRoute*>, and <xref:Microsoft.AspNetCore.Builder.ControllerEndpointRouteBuilderExtensions.MapAreaControllerRoute*> automatically assign an order value to their endpoints based on the order they are invoked. Matches from a route that appears earlier have a higher priority. Conventional routing is order-dependent. In general, routes with areas should be placed earlier as they're more specific than routes without an area. [Dedicated conventional routes](#dcr) with catch all route parameters like `{*article}` can make a route too [greedy](xref:fundamentals/routing#greedy), meaning that it matches URLs that you intended to be matched by other routes. Put the greedy routes later in the route table to prevent greedy matches.
193+
Adding routes using <xref:Microsoft.AspNetCore.Builder.ControllerEndpointRouteBuilderExtensions.MapControllerRoute*>, <xref:Microsoft.AspNetCore.Builder.ControllerEndpointRouteBuilderExtensions.MapDefaultControllerRoute*>, and <xref:Microsoft.AspNetCore.Builder.ControllerEndpointRouteBuilderExtensions.MapAreaControllerRoute*> automatically assign an order value to their endpoints based on the order they are invoked. Matches from a route that appears earlier have a higher priority. Conventional routing is order-dependent. In general, routes with areas should be placed earlier as they're more specific than routes without an area. [Dedicated conventional routes](#dcr) with catch-all route parameters like `{*article}` can make a route too [greedy](xref:fundamentals/routing#greedy), meaning that it matches URLs that you intended to be matched by other routes. Put the greedy routes later in the route table to prevent greedy matches.
194+
195+
[!INCLUDE[](~/includes/catchall.md)]
194196

195197
<a name="best"></a>
196198

0 commit comments

Comments
 (0)