I have few controllers that inherit from the same base class. Among the different actions that they don't share with each other, they do have a few that are completely identical. I would like to have these on my base class because they all work completely the same it's just that they're accessed through different routes.
How should I define these actions with several different routes?
My inherited classes also have a RoutePrefixAttribute
set on them so each of them is pointing to a different route.
Example
I have base abstract class called Vehicle
and then inherited Car
, Bike
, Bus
etc. All of them would have common action Move()
/bus/move
/car/move
/bike/move
How can I define action Move()
on my base class Vehicle
so that it will be executed on each subclass route?
Check the answer I gave here WebApi2 attribute routing inherited controllers, which references the answer from this post .NET WebAPI Attribute Routing and inheritance
What you need to do is overwrite the DefaultDirectRoutePrivider
:
public class WebApiCustomDirectRouteProvider : DefaultDirectRouteProvider {
protected override IReadOnlyList<IDirectRouteFactory>
GetActionRouteFactories(HttpActionDescriptor actionDescriptor) {
// inherit route attributes decorated on base class controller's actions
return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>(inherit: true);
}
}
With that done you then need to configure it in your web api configuration
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
.....
// Attribute routing. (with inheritance)
config.MapHttpAttributeRoutes(new WebApiCustomDirectRouteProvider());
....
}
}
You will then be able to do what you described like this
public abstract class VehicleControllerBase : ApiController {
[Route("move")] //All inheriting classes will now have a `{controller}/move` route
public virtual HttpResponseMessage Move() {
...
}
}
[RoutePrefix("car")] // will have a `car/move` route
public class CarController : VehicleControllerBase {
public virtual HttpResponseMessage CarSpecificAction() {
...
}
}
[RoutePrefix("bike")] // will have a `bike/move` route
public class BikeController : VehicleControllerBase {
public virtual HttpResponseMessage BikeSpecificAction() {
...
}
}
[RoutePrefix("bus")] // will have a `bus/move` route
public class BusController : VehicleControllerBase {
public virtual HttpResponseMessage BusSpecificAction() {
...
}
}
This is what I did and it worked the way you mentioned in your question.
I created base ApiController class and inherited all my API controllers from it. I defined Delete operation in my Base class (which returns string
"Not Supported") and didn't define delete on any of my child controller. Now when I do a delete on any of my controller I get the message "Not Supported" i.e. Base class's delete is called. ( I am doing Delete request on Child, and not on base i.e. /Bike/move)
But if I define a Delete on any of the controller it gives me warning of Hiding base implementation, but on doing Delete request for api I get - "An error has occurred."
I haven't tried doing RoutePrefix way.