0
votes

I have a ASP.NET Web API 2 controller in a custom Area. (I also have some API controllers in the default route)

I have registered the route:

// Web API routes
config.MapHttpAttributeRoutes();

// NEW ROUTE FOR AREAS
config.Routes.MapHttpRoute(
    name: "API Area MyArea",
    routeTemplate: "api/MyArea/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional });

My controller and method:

 [RoutePrefix("myarea/api/accountapi")]
  public class AccountAPIController : ApiController
  {
...

    [System.Web.Http.HttpGet]
    [AcceptVerbs("GET")]
    [AllowAnonymous]
    [Route("emailexists")]
    public async Task<IHttpActionResult> EmailExsists([FromUri]string email)
    {
      var user = await UserManager.FindByEmailAsync(email).ConfigureAwait(false);
      return Ok(user != null);
    }
...
}

But I can't get this to work, no matter what I try I get: https://localhost:44300/api/accountapi/[email protected]

{"message":"The requested resource does not support http method 'GET'."}

In fact, I can't get it to return an expected 404. For example, this: https://localhost:44300/api/accountapi/jibberish

Also returns a 405.

My API controllers in the default route works as expected, i.e. returning a 404 when it should.

Any ideas ?

1
Can you please show the code which is calling this API? It is most probably because you are making your API call with type: "POST". - Emre Bolat
Nope, sorry, I'm not. I'm explicitly doing GET from my client. - Magnus Johansson
Is there a reason why you've added a conventional route and an attribute route for your area? Regardless, there's a mismatch (the area and api segment are switched) between what you've specified as the conventional route (api/MyArea/{controller}/{id}) and the attribute route on the controller (myarea/api/accountapi). I think attribute routing overrides any conventional routing so the url you need to use with your current configuration is GET https://localhost:44300/myarea/api/accountapi/[email protected] - lawst

1 Answers

0
votes

Let's analyze the endpoints you are calling.

The first URI:

https://localhost:44300/api/accountapi/[email protected]

Looking at your routing configuration this will match only api/{controller}/{id} route template. That's because the first convention routing config will only match URI parts starting with api/MyArea, while the attribute routing prefix of your controller will only match paths starting with myarea/api/accountapi).

This will translate in the following route attributes:

  • {controller}: accountapi
  • {id}: emailexists
  • ?email: [email protected] (this will be ignored for routing purposes because is not included in the template)

Looking at your AccountAPIController I can't see any Action that allows GET and also has a string parameter called (explicitly) id: thus a 405 is returned.

The second URI:

https://localhost:44300/api/accountapi/jibberish

Will again only match the same route template as before:

  • {controller}: accountapi
  • {id}: jibberish

For the same reason a 405 response is returned.

What to do?

Your main problem is that you are mixing different routing methods without correctly matching the URI for your action. Without modifying the current route configuration the correct address for your EmailExsists method is the following one:

https://localhost:44300/myarea/api/accountapi/[email protected]

This will match your RoutePrefix and Route attributes in the AccountAPIController.

The following URIs should also match your action method based on the two routing convention you configured (they should be equivalent):

https://localhost:44300/api/[email protected]
https://localhost:44300/api/MyArea/[email protected]

My suggestion is to avoid the use of too many different routing templates and configurations: if you need the maximum flexibility use only attribute routing and remove the convention-based routing configuration.