Reputation: 3120
I am trying to configure a specific route to execute a message handler before it hits the controller, however the message handler is never executed.
I have the following controller:
public class TestController : ApiController
{
[Route("private/users")]
public IHttpActionResult Get()
{
return Ok();
}
}
And the following route configuration:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "private/users",
defaults: new { id = RouteParameter.Optional },
constraints: null,
handler: new TokenValidationHandler() { InnerHandler = new HttpControllerDispatcher(config) }
);
And The MessageHandler looks like this:
public class TokenValidationHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
//some logic to validate token
return base.SendAsync(request, cancellationToken);
}
}
The TokenValidationHandler is never executed which seems to be because of the routeTemplate when configuring the route. Is it possible to achieve route specific configuration with a hardcoded routeTemplate like "private/users" instead of the default "{controller}/{id}" format?
What I want to do is have my TokenValidationHandler fire for all of my private api calls and have public api calls bypass the TokenValidationHandler.
Upvotes: 1
Views: 1358
Reputation: 247068
Attribute routes a matched before convention-based routes. The action in question is tagged with an Route
attribute. If attribute routing is enabled then it means that it will not reach the convention-based route and thus not invoke the handler.
Remove the route attribute
public class TestController : ApiController {
public IHttpActionResult Get() {
return Ok();
}
}
The order of route registration also plays a factor for convention-based routes so make sure that general routes are registered after more specific routes
config.Routes.MapHttpRoute(
name: "PrivateApi",
routeTemplate: "private/users",
defaults: new { id = RouteParameter.Optional },
constraints: null,
handler: new TokenValidationHandler() { InnerHandler = new HttpControllerDispatcher(config) }
);
//more general route
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional },
//...
);
Otherwise if attribute routing is your preference you can consider using an action filter.
Based on stated intentions you would be better off using Authentication Filters in ASP.NET Web API 2
Upvotes: 2