0

My action method is set to accept only GET requests. If a verb other than GET is sent to it, an 'HTTP 405 Method not allowed' response would be sent back to the client. But I need to log it whenever a verb other than GET is sent to it. The way I am currently trying is by trying to raise an exception (I don't know which one to catch) and then do the logging inside the catch block. My action method is like as follows:

[RoutePrefix("api/Resource")]
public class MyController : ApiController
{
.
.
.
    [Route("MyRoute")]
    [ResponseType(typeof(IEnumerable<MyResource>))]
    [HttpGet]
    public async Task<IHttpActionResult> GetMyResourceAsync()
    {
        try
        {
            .
            .
            .
        }
        catch (WhichException e) // which exception do I catch here if a verb other than GET is sent by a client?
        {
            MyLogger.Log("Invalid http verb!");
        }

    }
.
.
.
}

When I try to access the resource using postman, and specify a verb such as POST or PUT, I get an HTTP 405 response, but I am unsure which exception to catch in my action method in order to intercept a non GET request. It need not necessarily be by raising an exception, but any other way to log a non GET request too would do.

halfer
  • 19,824
  • 17
  • 99
  • 186
Joonu Thomas
  • 318
  • 3
  • 4

1 Answers1

3

As mentioned in the comments, if you have a Http.Get (webapi-method), and you send a POST, that method is never going to fire. What you may be missing is that Http.Get is the default.

You may also want to review REST basic understandings.

http://encosia.com/rest-vs-rpc-in-asp-net-web-api-who-cares-it-does-both/

When your controller runs, it is a combination of the Method "Type" (GET, POST, PUT, DELETE) and the MethodName ( that microsoft handles for you)...that calls the method.

Thus a method that is decorated with [HttpGet] (or because of no attribute being applied ... which would then default to HttpGet) is NEVER going to fire for a POST request (sent over from the client). so your notion of "catching the errant method" does not make sense in a WebApi world.

Here is a better solution:

Consider writing an ActionFilter

Here is a simple one (that shows the Request.Method) (Obviously, you can filter on the Request.Method for non GET requests) :

 public class MyActionFilter : System.Web.Http.Filters.ActionFilterAttribute     /* from #region Assembly System.Web.Http.dll, v4.0.0.0     // C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET MVC     4\Assemblies\System.Web.Http.dll     #endregion */
 {
    public MyActionFilter()
    {
    }


    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        Console.WriteLine("OnActionExecuting:" + actionContext.Request.Method);
    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        Console.WriteLine("OnActionExecuted:" + actionExecutedContext.Request.Method);
    }
}

You can apply the filter to:

A method

AND/OR

A (webapi) Controller (Hint, if you want to add it to N number of "your" Api Controllers, create a base (abstract) controller, add the attribute to that controller and inherit the specific controller from the base/abstract controller )

OR

"Globally" with

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
    config.Routes.Blah.Blah.Blah; /* already existing code */

    /* this is the new code you need to add (line below) */
    config.Filters.Add(new MyActionFilter());
}
granadaCoder
  • 26,328
  • 10
  • 113
  • 146
  • Thanks a lot for your idea, I am trying it out now, will let you know if I'm able to successfully trap non GET requests – Joonu Thomas Feb 25 '16 at 11:13
  • Just one more question - apart from the action filter, do you think the same could be achieved using a custom message handler as well? – Joonu Thomas Feb 25 '16 at 11:14
  • You can add a custom Delegating Handler.......PRO Its earlier in the pipeline. CON its a "global only" thing...aka, you can't dwindle it down to a to a single controller or method. And you'll usually put in some "ignore this AbsoluteUri" hacks to ignore certain requests. – granadaCoder Feb 25 '16 at 14:17
  • Ok, I have some methods in my API to which I can send POST or PUT verbs, but some others which are supposed to accept only the GET verb. In this scenario, would a custom handler block all non GET requests, even to those methods that are fine with them? And if it does, can I supply some kind of configuration to the handler to exclude those uris? – Joonu Thomas Feb 25 '16 at 14:41
  • No idea. You'll have to Proof of Concept it. But you have the tools now to do what you need. – granadaCoder Feb 25 '16 at 14:48
  • sure, thanks, let me try out something, I'll post it once I have something! – Joonu Thomas Feb 25 '16 at 14:49