Search code examples
c#asp.net-mvcasp.net-web-apiasp.net-web-api-routing

Adding an Attribute Route without parameters in ASP.NET MVC 5


I have an API Controller Action defined as:

public async Task<IHttpActionResult> ChangePassword(string userId, string password)

My original plan was to pass both userId and password through the data attribute of an AJAX request instead of through the API url.

E.g.:

$.ajax({
    url: "/api/users/resetpassword",
    data: JSON.stringify({
        "userId" : userId,
        "password" : password
    }),
    dataType: "json",
    method: "POST",
    success: function () {
        $("#ResetPasswordModal").modal('toggle');
        toastr.success("Password Reset");
    },
    error: function () {
        $("#ResetPasswordModal").modal('toggle');
        toastr.error("Password could not be reset");
    }

});

However, if I apply the Attribute Route [Route("api/users/resetpassword")]

I get the error

No action was found on the controller 'Users' that matches the request

If I then replace the attribute route with [Route("api/users/{userId}/resetpassword/{password}")], the application is able to find the ChangePassword action successfully.

When applying Attribute Routes to Controller Actions, is it required that all attributes are included in the Route?


Solution

  • Create a model to hold the data sent from the client

    public class ChangePasswordModel {
        public string userId { get; set; }
        public string password { get; set; }
    }
    

    update the action to expect the data in the body of the request

    public class UsersController: ApiController {
    
        //...
    
        //POST api/users/resetpassword
        [HttpPost]
        [Route("api/users/resetpassword")]
        public async Task<IHttpActionResult> ChangePassword([FromBody]ChangePasswordModel data) {
            //...
        }
    
        //...
    }
    

    This assumes that attribute routing is already enabled in WebApiConfig.

    config.MapHttpAttributeRoutes();
    

    And is based on the following client details

    url: "/api/users/resetpassword",
    data: JSON.stringify({
        "userId" : userId,
        "password" : password
    }),
    dataType: "json",
    method: "POST",