Web API - Get RouteData, Action or Controller in DelegationHandler from HttpRequestMessage - asp.net-web-api

I am having a difficulty to get route data, action or controller in DelegatingHandler.
public class LoggingHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var routeData = request.GetRouteData();
in this example routeData is always null. Is there any way how to get the context of the Web API controllers and thus actions so I could tell what action the URL is trying to invoke?

Related

Bot Framework sending OPTIONS message

Recently, I have been getting 405 response messages logged in Application Insights from the bot framework relating to "OPTIONS" message being sent.
How should my service be responding to these?
Who is making these requests?
Sorry if you saw my previous answer; it was completely off base so I deleted it in shame.
The requests you mention are made by Azure when navigating to WebChat or the Settings tab. To allow the call, you can create a custom bot auth class:
public class CustomBotAuthenticationAttribute : BotAuthentication
{
public override Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
if (actionContext.Request.Method.Method == "OPTIONS") // allow OPTIONS through, and do not authenticate
return Task.CompletedTask;
return base.OnActionExecutingAsync(actionContext, cancellationToken);
}
}
Then, in the MessagesController:
[CustomBotAuthentication] // Change from [BotAuthentication]
public class MessagesController : ApiController
{
public HttpResponseMessage Options() // handle options
{
return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
}
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)

How to handle exception in IAuthenticationFilter interface?

I have created custom Authentication class using IAuthenticationFilter interface.
instead of using ChallengeAsync I have directly throw exception how to handle it ?
public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
HttpRequestMessage request = context.Request;
AuthenticationHeaderValue authorization = request.Headers.Authorization;
if (authorization == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.BadRequest,"FAIL"));
}
public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
{
//var challenge = new AuthenticationHeaderValue("Basic");
//context.Result = new AddChallengeOnUnauthorizedResult(challenge, context.Result);
//return Task.FromResult(0);
}
but how to handle exception throw?
From documentation: The HttpResponseException type is a special case, because it is designed specifically for returning an HTTP response. So you do not need to handle this exception. From ChallengeAsync code, I suppose you want to add authentication header to response if request was unauthorized. You can implement it like
public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
HttpRequestMessage request = context.Request;
var challenge = new AuthenticationHeaderValue("Basic");
var response = request.CreateResponse(HttpStatusCode.BadRequest, "FAIL");
response.Headers.WwwAuthenticate.Add(challenge);
throw new HttpResponseException(response);
}

Web Api and where should I contorol Request Header data

In Asp.net Web Api, I want to control, request "access token" key is (which is in request header) valid or not. But I cound't decide where should I implement this kind of control. ActionFilter or controller constructor etc. etc.
How about using a DelegatingHandler? It is part if the Web Api pipeline and executes before Routing and Controller handlers.
A really simple handler for access tokens may look like this. You would implement IsValid as you see fit.
public class ValidateTokenHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var token = request.Headers.Authorization;
if (token == null or !IsValid(token))
{
return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
}
return await base.SendAsync(request, cancellationToken);
}
}

APIController "Executed" method?

In an ApiController action I need to close a connection to a database as soon as the action is finished executing.
Under a controller I override OnActionExecuted to accomplish this.
How would I accomplish this under an ApiController action?
Thanks
You could override the ExecuteAsync method:
public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
{
return base
.ExecuteAsync(controllerContext, cancellationToken)
.ContinueWith(t =>
{
// the controller action has finished executing,
// your custom code could come here ...
return t.Result;
});
}

Adding message handler on the fly

I have four message handlers - MyHandler, MyHandler1, MyHandler2 and MyOtherHandler. I have MyHandler and MyOtherHandler added to the handlers collection, but not MyHandler1 or MyHandler2.
config.MessageHandlers.Add(new MyHandler());
config.MessageHandlers.Add(new MyOtherHandler());
I want MyHandler1 or MyHandler2 to be added to the pipeline on the fly by MyHandler, depending on some condition. I know that MyHandler1 and 2 can be added to the config.MessageHandlers collection and do nothing when their turn comes, when 'some' condition does not apply but that is not what I want. Let's say I have about 100 such handlers and I don't want all of them to run in the pipeline but only when MyHandler thinks it is appropriate.
I cannot manually insert MyHandler1 into the pipeline by setting MyHandler.InnerHandler. The chain is cached globally for all requests and I cannot modify it for something related to a specific request. Here is what I did.
I created a base handler that increases the visibility of SendAsync.
public abstract class MyBaseHandler : DelegatingHandler
{
public Task<HttpResponseMessage> WrapperSendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
return this.SendAsync(request, cancellationToken);
}
}
I derived MyHandler1 and 2 from this base.
public class MyHandler1 : MyBaseHandler
{
protected async override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
// Use request
var response = await base.SendAsync(request, cancellationToken);
// Use response
return response;
}
}
Now, MyHandler can instantiate MyHandler1 or Myhandler2 based on the condition and sets the InnerHandler to its own InnerHandler and just call and return SendAsync through the wrapper.
public class MyHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
// Check condition and choose MyHandler1 or MyHandler2 or just return
// await base.SendAsync(request, cancellationToken);
var h = new MyHandler1();
h.InnerHandler = this.InnerHandler;
return await h.WrapperSendAsync(request, cancellationToken);
// When MyHandler1 and MyHandler2 is no good, I just want
// to do nothing and let the other handlers do their job
// return await base.SendAsync(request, cancellationToken);
}
}
It does work but I'm not sure if I'm breaking something by doing this. Am I overlooking something by taking this approach?
Your approach looks good. I'm pretty sure it should work just fine.

Resources