moondaisy moondaisy - 1 month ago 28
ASP.NET (C#) Question

HttpMessageHandler with MapHttpAttributeRoutes not working

I'm follwoing this tutorial trying to get the behaviour of the MessageHandler3 in this image:
enter image description here

This is part of one of my controllers:

public class UserController : ApiController
{
[Route("api/users")]
[ResponseType(typeof(User))]
public IHttpActionResult PostUser([FromBody]User newUser)
{
try
{
userService.InsertUser(newUser);
return Ok(newUser);
}

catch (Exception e)
{
return BadRequest(e.Message);
}
}
}


This is a dummy version of the handler:

public class UserTokenHandler : DelegatingHandler
{
public UserTokenHandler()
{
}

protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
if (true)//actual validation method
{
var response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(response);
return tsc.Task;
}
return base.SendAsync(request, cancellationToken);
}
}


And here are the changes I have made to the WebApiConfig class:

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//config.MapHttpAttributeRoutes();
var handlers = new DelegatingHandler[] { new UserTokenHandler() };
var routeHandlers = HttpClientFactory.CreatePipeline(new HttpControllerDispatcher(config), handlers);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: null,
handler: routeHandlers
);
config.MapHttpAttributeRoutes();
}
}


My problem is with the commented line. If I don't include it or put it at the end (like it is now) the handler executes but then I get this error when trying to use my api:

{
"Message": "No HTTP resource was found that matches the request URI 'http://localhost:12986/api/users'.",
"MessageDetail": "No type was found that matches the controller named 'users'."
}


But if I uncomment it (and remove the one of the bottom) I go directly to the controller without going through the handler.

I would like it to go through the handler and then find the method, how can I fix it?

Answer

You can actually add handler before mapping if you want.

config.MessageHandlers.Add(new UserTokenHandler());
config.MapHttpAttributeRoutes();
//...other code

I've done this do implement throttle handlers and works like a charm but this would apply to all requests coming in.

If you want this to apply for only the users controller then you need to give up on the attribute route and use convention-based route for the user controller.

If however you have a mix of convention-based and attribute routes then that wont mix well, because as in the article you linked to. This is better tailored for convention-based routing.