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

How to pass multiple params to WebAPI?


I have the following URL:

http://localhost/api/values/100/some+string+here

In the WebAPI app ValuesController, I have this:

[HttpGet]
[Route("api/values/{p1}/{p2}")]
public HttpResponseMessage Get (string p1, string p2) {
...
}

For the caller, it never hits the web api. Instead, it comes back with a 404.

Any idea what is wrong?


Solution

  • You are using Attribute Routing in ASP.NET Web API 2. Make sure you configure your web api to use Attribute routing with MapHttpAttributeRoutes.

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

    Next make sure you defined your controller properly

    public class ValuesController : ApiController {
        //GET api/values/100/some-string-here
        [HttpGet]
        [Route("api/values/{p1}/{p2}")]
        public HttpResponseMessage Get (string p1, string p2) {
        ...
        }
    }
    

    You could even use RoutePrefix

    [RoutePrefix("api/values")]
    public class ValuesController : ApiController {
        //GET api/values/100/some-string-here
        [HttpGet]
        [Route("{p1}/{p2}")]
        public HttpResponseMessage Get (string p1, string p2) {
        ...
        }
    }
    

    Also if like in your example you want the first parameter to be an integer. then you can use a route constraint and update method.

    [RoutePrefix("api/values")]
    public class ValuesController : ApiController {
        //GET api/values/100/some-string-here
        [HttpGet]
        [Route("{p1:int}/{p2}")]
        public HttpResponseMessage Get (int p1, string p2) {
        ...
        }
    }
    

    UPDATE:

    Created an integration test for the Values Controller and was able to confirm that the action was called

    [TestMethod]
    public async Task HttpClient_Should_Get_OKStatus_From_Action_With_Multiple_Parameters() {
        var config = new HttpConfiguration();
        config.MapHttpAttributeRoutes();
    
        using (var server = new HttpServer(config)) {
    
            var client = new HttpClient(server);
    
            string url = "http://localhost/api/values/100/some+string+here";
    
            using (var response = await client.GetAsync(url)) {
                Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
            }
        }
    }