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/emailexists?email=info@something.com
{"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 ?
Let's analyze the endpoints you are calling.
https://localhost:44300/api/accountapi/emailexists?email=info@something.com
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
: info@something.com (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.
https://localhost:44300/api/accountapi/jibberish
Will again only match the same route template as before:
{controller}
: accountapi{id}
: jibberishFor the same reason a 405 response is returned.
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/emailexists?email=info@something.com
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/accountapi?email=info@something.com
https://localhost:44300/api/MyArea/accountapi?email=info@something.com
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.