-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Plan to migrate IRouter based implementations onto Endpoint Routing #4221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
/cc @davidfowl @JamesNK |
Is it possible that Endpoint Routing be implemented as a |
URL rewriting isn't routing though, why would use use routing to rewrite the URL? We have a URLRewrite middleware specifically for that purpose. You run that before routing makes the decision on what end point gets selected. |
I mean the routers that want to supply route values and choose actions, and these may want to do link generation too |
The contract of 'endpoint routing' in 3.0 is to produce an instance of There can be any number of middleware that participate in this cooperatively. There's no reason why you couldn't write an Link generation is a little more complicated because it's not cooperative - but basically you can choose to implement an 'address scheme' which describes how you find a set of endpoints to attempt to use for link generation. If you're trying to extend the system, broadly, then maybe the right thing to do is create an 'address scheme' that matches your requirements and implement it. If you're trying to extend an 'in the box' scheme (like MVC's link generation), the you'll have to replace it and provide an implementation that does what you want. Generally the kinds of things that lead folks to implement If you really do want to implement routing extensibility then the most reasonable path would be to provide us with all of the endpoints, and we will work it out. If this is something that's impossible for your scenarios, then I'd like to learn more. My experience helping others understand how to implement routing from WebAPI2/MVC5 -> current is that generally extenders expect a purpose-built extensibility point to exist for what they are trying to do, and shy away from re implementing anything. Generally in the routing arena it's going to be the case moving forward that you will need to write code if you want to reprogram routing. This is a philosophical pivot on our part to trade openness for performance and features. We think this is the right thing to do because routing is going to be part of just about every scenario. If you feel like you're blocked, that's not great and we need to make it better. |
Done for 2.2 |
I've just found this via 2.2 -> Endpoint routing https://blogs.msdn.microsoft.com/webdev/2018/08/27/asp-net-core-2-2-0-preview1-endpoint-routing/ I maintain Carter - https://github.com/CarterCommunity/Carter/tree/master/src and this leverages the routing middleware. Carter registers routes via I'd like to know how that will affect Carter if you plan to move away from IRouter. I assume you will still have routing middleware? The reason for the existence of Carter is because I want the functionality of having the path next to the handler
If that made it into MVC then that'd be awesome but noone at MS seems interesting in that even though the routing middleware provides that functionality. If you'd like to work together on trying to move Carter onto the new things you're proposing that'd be awesome, would be beneficial for both parties imo. Thanks |
Quick intro to endpoint routing:
This example of Startup.cs has a mix of using the helper methods and registering MVC endpoints - https://github.com/aspnet/AspNetCore/blob/master/src/Mvc/samples/MvcSandbox/Startup.cs#L35-L70 MVC's endpoint datasource - https://github.com/aspnet/AspNetCore/blob/master/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Routing/MvcEndpointDataSource.cs It should be fairly simple for you to move from using |
Thanks.
Guess I need to sit down and spike Carter using endpoint routing. Is that
currently possible or should I wait closer to aspnetcore v3 for the apis to
be decided as I know there are plans to change it quite a lot from 2.2 to 3
so frameworks can consume them.
…On Thu, 6 Dec 2018 at 10:24, James Newton-King ***@***.***> wrote:
Quick intro to endpoint routing:
1. A RouteEndpoint has a template, metadata, and a request delegate
that will serve the endpoint's response
2. Endpoint datasources are mapped when the UseEndpointRouting
middleware is registered. This middleware will handle matching the
template. At the end of the request pipeline a matched endpoint's request
delegate is automatically called
3. If your endpoints are static, e.g. they don't change during the
lifetime of the application, then you can map endpoints using MapGet,
MapPost, and MapVerbs helper methods
4. If your endpoints are dynamic, e.g. a new Razor page is added to
the app at runtime and needs a new endpoint, then you would create a custom
data source
This example of Startup.cs has a mix of using the helper methods and
registering MVC endpoints -
https://github.com/aspnet/AspNetCore/blob/master/src/Mvc/samples/MvcSandbox/Startup.cs#L35-L70
MVC's endpoint datasource -
https://github.com/aspnet/AspNetCore/blob/master/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Routing/MvcEndpointDataSource.cs
Custom framework using endpoint routing - davidfowl/uController#6
<davidfowl/uController#6>
------------------------------
It should be fairly simple for you to move from using
IRouteBuilder.MapRoute to the Map/MapGet/MapPost/MapVerb/etc extension
methods that hang of IEndpointBuilder.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#4221 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAGapnOK1I4f0aqvrOrff_FudVTfaW_gks5u2PB2gaJpZM4Yufy4>
.
|
Out of interest can you see any possibility of having mvc deal with routing
like the current routing middleware and carter behaves with the new
endpoint routing ie you have a path and handler next to each other?
On Thu, 6 Dec 2018 at 10:38, Jonathan Channon <[email protected]>
wrote:
… Thanks.
Guess I need to sit down and spike Carter using endpoint routing. Is that
currently possible or should I wait closer to aspnetcore v3 for the apis to
be decided as I know there are plans to change it quite a lot from 2.2 to 3
so frameworks can consume them.
On Thu, 6 Dec 2018 at 10:24, James Newton-King ***@***.***>
wrote:
> Quick intro to endpoint routing:
>
> 1. A RouteEndpoint has a template, metadata, and a request delegate
> that will serve the endpoint's response
> 2. Endpoint datasources are mapped when the UseEndpointRouting
> middleware is registered. This middleware will handle matching the
> template. At the end of the request pipeline a matched endpoint's request
> delegate is automatically called
> 3. If your endpoints are static, e.g. they don't change during the
> lifetime of the application, then you can map endpoints using MapGet,
> MapPost, and MapVerbs helper methods
> 4. If your endpoints are dynamic, e.g. a new Razor page is added to
> the app at runtime and needs a new endpoint, then you would create a custom
> data source
>
> This example of Startup.cs has a mix of using the helper methods and
> registering MVC endpoints -
> https://github.com/aspnet/AspNetCore/blob/master/src/Mvc/samples/MvcSandbox/Startup.cs#L35-L70
>
> MVC's endpoint datasource -
> https://github.com/aspnet/AspNetCore/blob/master/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Routing/MvcEndpointDataSource.cs
> Custom framework using endpoint routing - davidfowl/uController#6
> <davidfowl/uController#6>
> ------------------------------
>
> It should be fairly simple for you to move from using
> IRouteBuilder.MapRoute to the Map/MapGet/MapPost/MapVerb/etc extension
> methods that hang of IEndpointBuilder.
>
> —
> You are receiving this because you commented.
> Reply to this email directly, view it on GitHub
> <#4221 (comment)>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AAGapnOK1I4f0aqvrOrff_FudVTfaW_gks5u2PB2gaJpZM4Yufy4>
> .
>
|
Endpoint Routing moves down to a low level a bunch of things that used to only be done in MVC. So if you're authoring a framework, you should find it a lot more powerful. We'll be revising some of the patterns around startup in 3.0 to make this more first class. Right now (2.2) the ability to interact with routing is still kinda hidden inside MVC. |
I have a multitenant library which supports several ways to detect a tenant. One of them is via a route parameter. This detection happens in middleware prior to I currently "run" routing in my middleware before the MVC middleware runs. I do this (approximately) by reimplementing It's unclear to me how this new approach will impact my approach. Is there now a better way to get the RouteData prior to the MVC middleware being called? Thanks! |
@aKzenT - I plan to enable scenarios like yours as part of the next preview release. I'll update this issue when I have something to share. Thanks for the feedback. |
I'm also using IRouter based custom route to change RouteValues (or in other words, intercept routing) and let MVC action selectors select custom action. This obviously fails in asp.net core 2.2. So I tried to implement this interception using middleware. To test out the prototype, I tried following and it works. app.UseEndpointRouting();
app.Use(async (context, next) => {
var selectorContext = context.Features.Get<IEndpointFeature>() as EndpointSelectorContext;
selectorContext.RouteValues["action"] = "NonExistentAction";
await next();
});
app.UseMvc(); You can intercept endpoint routing before MVC action selectors run, and change route values however you want. This obviously doesn't facilitate in link generation, but as explained by @rynowak, that's a hardly a feature we need for this kind of interception, even when using IRouter. So here it goes for those who are still looking for a way to make IRouter based extensibility work in asp.net core 2.2. By the way, I was also using IRouter based routes in my own custom CMS framework, and also for mapping SLUG urls. And this new middleware based method works just fine. You can attach special data token in your routes to identify them as needing special handling, and inside your middleware, you can handle accordingly. I can share more complete solution if anyone needs further. Thanks |
@joshua-mng how do you add new routes to the system when new pages are created in the CMS? |
@joshua-mng I would be interested to see a more complete sample, do you have a github repo for it? |
Hi all, I also had an issue with dynamic endpoint routing when change from old routing (using IRouter). I followed @joshua-mng's suggestion, I implemented middleware to redirect enpoint at runtime by changing EndpointSelectorContext, Another way we can solve this issue out without using middleware, we can use extension function Map(string pattern, RequestDelegate requestDelegate) that map generic route with generic requestDelegate, its job is extracting genericSlug parameter to slug string, search slug in database, then invoke approriate page action. For details, please refer to below code: `public static IEndpointConventionBuilder MapFallbackToGenericPage(
I also added this implementation into above project. I hope this help. |
Just an FYI this code wiil not work in 3.0, casting the |
@davidfowl My project is built for 3.0-preview-4, I tested and it worked. Please give it a try. Thanks! |
It’ll be broken in preview6. |
Hi,
|
My proposed workaround above is not working anymore, don't know why. Although endpoint routing gives more flexibility and performance for other consumers (cors, mvc, and others), it's currently damn hard to extend it. It should be simple enough. According to people discussing various problems they encounter above, only simple solution we all want is:
It's this simple, but it doesn't work anymore. Currently only workaround is to disable endpoint routing, but what happens when version 3 is out soon in fall. Hope we will have better and easier option to implement this in version 3.0 |
I've created a PR for this here: #8955 It works roughly the way @joshua-mng suggested. If you're interested in this area, please take a look at this and let me know if this works for your needs. |
This has been merged for preview 7. Look for more details in the announcement post when preview 7 is available. |
👏 |
tldr; for developers with custom IRouter implementations:
services.AddMvc(options => options.EnableEndpointRouting = false)
Summary
I'm developing a plan to make it possible for folks implementing
IRouter
based functionality to migrate endpoint routing. This is our future direction for MVC and the stack in general, and we don't want to leave users/frameworks behind.I'm also lumping in this category custom
IActionSelector
implementations.IActionSelector
is not used in endpoint routing so it's just as relevant/obsolete for new apps.Over time we're going to evolve in the direction of endpoint routing being the primary experience for the whole stack. I don't expect that we'd ever be able to delete
IRouter
or removeIRouter
support from MVC. We can offer users more options to migrate and try to make it as enticing as possible, but some portion will be left behind; either by our choice not to add a feature they want, or their choice not to adopt new features and concepts.Analysis
Based on analysis, I've found 3 major types of usages:
Note that these are roughly in ascending order of 'off-road-ness' - reusing less of our implementation gradually. Most genuine challenges in framework design related to application authors writing extensibility that uses and is used by the framework.
Let's go case by case and look at these...
I want to rewrite the route values
Usually the case for this is that you want to have one set of actions that you 'multiply' (cross-product) across different localized strings that you want to appear in the URL. There's a major pivot here regarding whether you want to localize the 'route values' or just localize the URL template.
In general all of these things 'just work' with application model today. Some users choose to implement this with
IRouter
because they have done that in the past or it's what seems most obvious to them, but there's no real problem with using application model for this.My route values in the database
Generally this kind of system works by defining a
slug
route in the route table that matches all URLs, and then looking up a set of route values in a database using the URL path or part of it as a key.Example:
This requires a slightly more involved solution, because the route templates can't be defined statically, and because we don't provide a simple way to 'run code' to select an MVC action. My assumption here is that this user doesn't want to access the DB once on startup to create the route table, they want to make configuration changes while the app is running.
The key here is that this user is reusing MVC's action selector by rewriting the route values.
Here's a proposal:
IEndpointSelectorPolicy
can be filter where it applies by candidate set. This is for isolation.This has a few drawbacks:
Another approach would be to rewrite the URL. That might be more straightforward.
I am implementing a framework
Upon further analysis, this case is very similar to the above. The framework registers a route that matches a 'slug', and has a custom implementation that produces an action.
This case has fewer drawbacks because they are not using MVC's action selection.
Next steps
We need to do this. This is a nice perf enhancement to
IEndpointSelectorPolicy
and can unblock a framework like OData migrate. We need to do this in 2.2 so it's not a breaking change.We should consider further whether URL rewriting is a better solution for most of these scenarios.
I think the timeframe for any other choices we'd consider is 3.0
The text was updated successfully, but these errors were encountered: