Let's imagine I have a "platform" with some basic features. It has its own set of controllers with actions delivered as a class library. For example, let's name it as CartController
with Order
action, as a result, API URL will be Cart/Order
.
For some reason, I want to extend logic in Order process, I added MyCartController
with Order
action in my project where I reference the platform. Now I need to set up the app to use my custom action instead of the original one.
In ASP MVC 5 (based on .NET Framework) I can do it as follows
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
var route = new Route("Cart/Order", new RouteValueDictionary(new Dictionary<string, object>
{
{ "action", nameof(MyCartController.Order) },
{ "controller", nameof(MyCartController).Replace("Controller", "") }
}), new MvcRouteHandler());
routes.Insert(RouteTable.Routes.Count - 2, route);
}
}
and then call it from Startup as
public override void Configuration(IAppBuilder builder)
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
and it worked well.
But after migration to .NET Core 5, it stopped working. In Startup, I added
public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute("MyCartOrder", "Cart/Order", new { controller = nameof(MyCartController).Replace("Controller", ""), action = nameof(MyCartController.Order) });
});
}
with no luck. It looks like they broke something helpful here https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.Core/src/Routing/ControllerActionEndpointDataSource.cs#L100
I tried to decorate my controller with Route("Cart")
attribute and HttpPost("Order")
with AmbiguousMatchException: The request matched multiple endpoints
exception.
I have no idea of how to override it then.
So my question is: How to override the route to use my action on my controller in .Net Core 5? What is the equivalent of routes.Add from .Net 4.8 which works for URL matching but not only for links generation?
Any thoughts and ideas will be appreciated.
You can mark the needed action in the "override" controller with Http{Method}Attribute
and set Order
property to some value (by default -1 should do the trick):
[HttpPost("Order", Order = -1)]
HttpMethodAttribute.Order
Property:
Gets the route order. The order determines the order of route execution. Routes with a lower order value are tried first. When a route doesn't specify a value, it gets the value of the Order or a default value of 0 if the
RouteAttribute
doesn't define a value on the controller.
Or set the property with the same name of RouteAttribute
on the controler:
[Route("Cart", Order = -1)]