Search code examples
.netasp.net-web-apiasp.net-web-api2asp.net-web-api-routing

Incorrect endpoint firing using Route attribute


I have the following methods in my UserController. The first two, Register and VerifyUser work fine.

However - I can't get login to be called. No matter what combination of URLs I try - the Register method fires.

[RoutePrefix("api/user")]
public class UserController : ApiController
{
    [Route("Register")]
    [HttpPost]
    public HttpResponseMessage Register([FromBody]RegisterUserModel model)
    {
        ....
    }

    [HttpGet]
    [Route("{email}/{verifyId}")]
    public HttpResponseMessage VerifyUser(string email, string verifyId)
    {
        ....
    }

    [Route("Login")] //Not being fired - Register being fired
    [HttpPost]
    public HttpResponseMessage Login([FromBody]RegisterUserModel userMod)
    {
        ....
    }
}

Am I missing something obvious?


Solution

  • What is happening is that you most likely have the default convention based route only

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

    which would map to register first and not bother to check Login.

    calling api/user/Login would map to the api/{controller}/{id} convention route with Login being mapped to the id placeholder. The route table to use the HTTP verb POST to find the first action that could handle a post with the provided body. It would find register first and map to that action.

    Check to make sure attribute routing is enabled in WebApiConfig ie

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

    The comments in the following shows the Url that maps to the actions.

    [RoutePrefix("api/user")]
    public class UserController : ApiController {
    
        //Matches POST api/user/register
        [Route("Register")]
        [HttpPost]
        public IHttpActionResult Register([FromBody]RegisterUserModel model) {
            //....
        }
    
        //Matches GET api/user/some_email/some_id
        [HttpGet]
        [Route("{email}/{verifyId}")]
        public IHttpActionResult VerifyUser(string email, string verifyId) {
            //....
        }
    
        //Matches POST api/user/login
        [Route("Login")]
        [HttpPost]
        public IHttpActionResult Login([FromBody]RegisterUserModel userMod) {
            //....
        }
    }
    

    Reference Attribute Routing in ASP.NET Web API 2