Reputation: 6679
In an ASP.NET 4.5 MVC 4 Web API project, I want to add a custom HttpMessageHandler
. I've changed WebApiConfig
class (in \App_Satrt\WebApiConfig.cs), as follows:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: null,
handler: new MyCustomizedHttpMessageHandler()
);
}
}
Then I developed MyCustomizedHttpMessageHandler
:
public class MyCustomizedHttpMessageHandler : HttpMessageHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
IPrincipal principal = new GenericPrincipal(
new GenericIdentity("myuser"), new string[] { "myrole" });
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;
return Task<HttpResponseMessage>.Factory.StartNew(() => request.CreateResponse());
}
}
However, the request to the API (let's say http://mylocalhost.com/api/values), always returns status code 200, without any data. I mean it never gets to ValuesController.cs's 'GET()' method.
What have I missed? How can I implement HttpMessageHandler
properly?
PS: Have already read this one: https://stackoverflow.com/a/12030785/538387 , doesn't help me.
Upvotes: 19
Views: 45355
Reputation: 1918
I used @cuongle answer to solve my problem. Just with one addition. So I did not get "The inner handler has not been assigned.". Thank you @coungle.
public class CustomMessageHandler : DelegatingHandler
{
public CustomMessageHandler ()
{
//add this to solve "The inner handler has not been assigned"
InnerHandler = new HttpClientHandler();
}
protected override async Task<HttpResponseMessage>
SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Before request
IPrincipal principal = new GenericPrincipal(
new GenericIdentity("myuser"), new string[] { "myrole" });
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;
var result = await base.SendAsync(request, cancellationToken);
// After request when response arrives
return result;
}
}
Upvotes: 1
Reputation: 57949
Here you are creating a HttpMessageHandler
which short circuits the request and doesn't let the request pass through the rest of the pipeline. Instead, you should create a DelegatingHandler
.
Also there are 2 kinds of message handler pipelines in Web API. One is a regular pipeline in which all requests for all routes pass through and other where one could have message handlers specific to certain routes only.
Try to create a DelegatingHandler
and add it to your HttpConfiguration
's list of message handlers:
config.MessageHandlers.Add(new HandlerA())
If you want to add a route specific message handler, then you could do the following:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: null,
handler:
HttpClientFactory.CreatePipeline(
new HttpControllerDispatcher(config),
new DelegatingHandler[]{new HandlerA()})
);
This Web Api Poster shows the pipeline flow.
Upvotes: 24
Reputation: 75306
To write a custom message handler, you should derive from System.Net.Http.DelegatingHandler
class CustomMessageHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage>
SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
IPrincipal principal = new GenericPrincipal(
new GenericIdentity("myuser"), new string[] { "myrole" });
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;
return base.SendAsync(request, cancellationToken);
}
}
And call base.SendAsync
to send the request to the inner handler.
Upvotes: 17