For my API, I want to be able to handle scenarios where the call is made using an incorrect URL (i.e. URL that does not match any controller or action.)
For this I have implemented routing so that it matches any route:
config.Routes.MapHttpRoute(
name: "CatchAll",
routeTemplate: "{*any}",
defaults: new { controller = "Error", action = "Handler" }
);
And I have implemented the controller - action as follows:
[Route("api/v1/Handler")]
[ActionName("Handler")]
public HttpResponseMessage Get() {...}
When I give an incorrect URL, I get the message:
No action was found on the controller 'Error' that matches the name 'Handler'
Not sure where the mistake is.
Simple approach:
You need to match the action name. So either rename Get
to Handler
in the ErrorController
and remove attributes as they will conflict with conventions you mapped .
public HttpResponseMessage Handler(string any) {...}
or change action from Handler
to Get
in the Catch all MapHttpRoute
config.Routes.MapHttpRoute(
name: "CatchAll",
routeTemplate: "{*any}",
defaults: new { controller = "Error", action = "Get" }
);
Not so simple approach:
Here is how I handled the same thing in my web api using attribute routing and inheritance.
First I created a base api controller that will handler unknown actions.
public abstract class WebApiControllerBase : ApiController {
[Route("{*actionName}")]
[AcceptVerbs("GET", "POST", "PUT", "DELETE")]
[AllowAnonymous]
[ApiExplorerSettings(IgnoreApi = true)]
public virtual HttpResponseMessage HandleUnknownAction(string actionName) {
var status = HttpStatusCode.NotFound;
var message = "[Message placeholder]";
var content = new { message = message, status = status};
return Request.CreateResponse(status, content);
}
}
My Api controllers all inherit from this base controller.
[RoutePrefix("api/customers")]
public class CustomersApiController : WebApiControllerBase {...}
Given that your question included RouteAttribute
you should already be using MapHttpAttributeRoutes
in your web api config.
But there's more. To get the framework to recognize the inherited attributes you need to override the DefaultDirectRouteProvider
as outlined here
and used in an answer here
WebAPI controller inheritance and attribute routing
public class WebApiCustomDirectRouteProvider : DefaultDirectRouteProvider {
protected override System.Collections.Generic.IReadOnlyList<IDirectRouteFactory>
GetActionRouteFactories(System.Web.Http.Controllers.HttpActionDescriptor actionDescriptor) {
// inherit route attributes decorated on base class controller's actions
return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>(inherit: true);
}
}
and apply that to the web api configuration.
// Attribute routing. (with inheritance)
config.MapHttpAttributeRoutes(new WebApiCustomDirectRouteProvider());
Hope this helps