6

I am looking for a way to intercept/grab the request being made before matching to a route. For example, I have multiple controllers and routes set up, but I want some mechanism in which will be hit before the route method is hit. It would be highly preferable if this mechanism were able to get the route params that were sent.

I have been unable to find something similar to what I am looking for (but perhaps not being well versed in Web API I am searching with the wrong keywords).

Luke G
  • 367
  • 1
  • 4
  • 20

4 Answers4

10

What you need is action filters. You can apply action filters directly to controllers as attributes, the caveat with Action filters is that at this point the controller route is already known but you can still control (very much like AOP) if the action method can be executed or not:

ASP.NET Web API ActionFilter example

Look at how you can use an action filter, in this case for logging:

public class LogActionFilter : ActionFilterAttribute 
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        Log(actionExecutedContext.ActionContext.RequestContext.RouteData);

        base.OnActionExecuted(actionExecutedContext);
    }

    private void Log(System.Web.Http.Routing.IHttpRouteData httpRouteData)
    {
        var controllerName = "controller name";
        var actionName = "action name";
        var message = String.Format("controller:{0}, action:{1}", controllerName, actionName);

    Debug.WriteLine(message, "Action Filter Log");
    }
}

How to log which action method is executed in a controller in webapi

You can also use message handlers, which are executed before the controller is resolved:

HTTP Message Handlers in ASP.NET Web API

Community
  • 1
  • 1
MeTitus
  • 3,390
  • 2
  • 25
  • 49
  • 2
    `I am looking for a way to intercept/grab the request being made before matching to a route` -- action filters occur after a route has been matched, no? It may also be the case that the question is just not clear enough to provide a proper answer – Tung Oct 29 '15 at 21:10
  • If that is what you want you can use message handler, what is it you need to do before the route is discovered? – MeTitus Oct 29 '15 at 21:12
  • I'm just quoting a part of the question from the OP because I think your answer may have missed that aspect of it :) – Tung Oct 29 '15 at 22:21
  • Perhaps I misspoke saying before the match happens. What I mean is before the method that is matched on is called. In this case I was able to use 'OnActionExecuting' in order to hit that block of code before the method within the controller is called. This is exactly what was needed, and looked to be the overall best solution for me – Luke G Oct 30 '15 at 12:05
  • For most of the cases action filter are fine, glad I could help :-) – MeTitus Oct 31 '15 at 20:00
6

I'm using mentioned technique to log all requests and responses. Speaking shortly, the best way to do it is to use Handlers.

First, create handler:

public class CustomHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        //get route values and process them
        var routeValues = (IHttpRouteData[]) HttpContext.Current.Request.RequestContext.RouteData.Values["MS_SubRoutes"];

        //let other handlers process the request
        return await base.SendAsync(request, cancellationToken)
            .ContinueWith(task =>
            {
                //once response is ready, do something with it                                        

                return task.Result;
            }, cancellationToken);
    }
}

Then, register it in WebApiConfig:

config.MessageHandlers.Add(new CustomHandler());
balbelias
  • 428
  • 5
  • 17
  • If you use delegate handlers to log all the requests you will also log invalid requests, if all you need is to logging you should use action filters not handlers. – MeTitus Oct 29 '15 at 20:50
  • @Marco those ones interested me too :) – balbelias Oct 29 '15 at 20:58
  • Both of them allow you to log your requests, but with action filters is easier for you to log only meaningful data :) – MeTitus Dec 30 '15 at 17:51
0

Would it work to create a HttpHandler (or do it just in Global asax Application_BeginRequest event) to capture the requests and inside the handler parse the URL against route config, similar to this link.

Community
  • 1
  • 1
Martin Staufcik
  • 8,295
  • 4
  • 44
  • 63
0

Like Joel Etherton mentioned in the comments, I think what you are looking for is something like adding the following code in your global.asax:

protected void Application_EndRequest()
{
    /*
    if(HttpContext.Current.Response.StatusCode == 404)
        Debug.WriteLine("404 something something")
    if(HttpContext.Current.Response.StatusCode == 500)
        Debug.WriteLine("500 something something")
    if(HttpContext.Current.Response.StatusCode == 200)
        Debug.WriteLine("200 something something")
    */
    Debug.WriteLine($"{context.Response.StatusCode} - {request.Url.PathAndQuery}");
}

I got my inspiration from here: ASP.NET MVC 404 Error Handling

hormberg
  • 184
  • 2
  • 8