ASP.NET Core 10: Clearer separation between middlewares and endpoints for more predictable routing
Introduction
If you’ve been working with ASP.NET Core long enough, you’ve probably been bitten at least once by middleware ordering issues. Putting UseAuthentication() before UseRouting(), or UseAuthorization() in the wrong spot, these mistakes are subtle, they don’t throw exceptions, and they lead to hours of debugging auth failures that make no sense.
ASP.NET Core 10 improves on this by making the separation between middlewares and endpoints clearer and more predictable out of the box.
The old problem and what changed
Before ASP.NET Core 10, the order of your middleware registrations was critical, and the framework didn’t always help you get it right. UseAuthentication() runs before UseRouting(), which means it doesn’t yet know which endpoint the request is heading to. That’s a problem because authentication and authorization middleware often need to inspect endpoint metadata (like [Authorize] attributes) to make correct decisions. The result? Silent failures, requests would get rejected or allowed through incorrectly, with no obvious error telling you what went wrong.
With ASP.NET Core 10, WebApplication does a better job of handling the routing/endpoint lifecycle internally. Routing is now implicit in most scenarios, the framework inserts UseRouting at the correct position in the pipeline even if you don’t call it explicitly. This means that middleware like authentication and authorization always has access to endpoint metadata, regardless of where you register it relative to UseRouting:
Whether you call UseRouting() explicitly or let the framework handle it, routing runs early enough that subsequent middleware can reliably inspect which endpoint was matched and what metadata it carries. This isn’t a dramatic API change, it’s the framework getting smarter about when routing happens in the pipeline, so that a misplaced call no longer silently breaks your security layer.
What about custom middleware?
This is an important question: does this improvement apply to custom middleware too, or only to built-in ASP.NET Core middleware?
The short answer is: it depends on what your middleware does.
If your custom middleware reads endpoint metadata, for example, calling context.GetEndpoint() to inspect attributes or routing information, it benefits from the same implicit routing behavior. Since UseRouting now runs early in the pipeline by default, your custom middleware will see the matched endpoint regardless of where it’s registered.
For instance, a custom middleware that checks for a specific attribute on the matched endpoint will work correctly without you having to worry about placing it after an explicit UseRouting() call:
On the other hand, if your custom middleware doesn’t interact with routing at all, say, a simple request logging or correlation ID middleware, it was never affected by this ordering issue in the first place.
One thing that hasn’t changed
The relative order of UseAuthentication() and UseAuthorization() still matters. Authentication must run before authorization, because authorization needs a resolved identity to work with. The improvement here is specifically about routing metadata being available earlier, it doesn’t magically resolve every possible ordering dependency between middlewares.
Conclusion
This is one of those changes that won’t change how you write code day-to-day, but it removes a classic trap that has caught many developers over the years. By making routing implicit and ensuring endpoint metadata is available early in the pipeline, ASP.NET Core 10 eliminates a whole category of silent middleware ordering bugs. If you write custom middleware that reads endpoint metadata, you get the same benefit for free.