Reputation: 318
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.
Upvotes: 0
Views: 681
Reputation: 27862
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());
}
Upvotes: 3