How to pass/receive multiple args to a RESTful Web API GET method?

B. Clay Shannon picture B. Clay Shannon · Nov 10, 2013 · Viewed 42.9k times · Source

The usual examples of GET RESTful methods that take a parameter (returning a scalar value rather than a dataset) are shown like so:

public string Get(int id)
{
    //get and return the value
}

...where the val passed is typically an ID, so you can use it to get a scalar value based on that unique value.

What, though, if you want to pass multiple values, such as a string and an int? Is it simply a matter of defining a method like so:

public string Get(string someString, int someInt)
{
    //get and return the value
}

...and calling it like so:

//const string uri = "http://192.112.183.42:80/api/platypusItems/someString/someInt";, zB:
const string uri = "http://192.112.183.42:80/api/platypusItems/DuckbilledPlatypisAreGuysToo/42";
var webRequest = (HttpWebRequest) WebRequest.Create(uri);

?

IOW, will the routing mechanism figure out that, since two args are passed, it should call the Get() method with two args ("convention over configuration"), or is there more that has to be done to route things appropriately?

Answer

Nikolai Samteladze picture Nikolai Samteladze · Nov 10, 2013

If you use Web API 2, then you can use Attribute Routing to route requests like http://192.112.183.42:80/api/platypusItems/DuckbilledPlatypisAreGuysToo/42

public class ItemsController : ApiController
{ 
    [Route("api/{controller}/{id}")]
    public string GetItemById(int id)
    {
         // Find item here ...

         return item.ToString();
    }

    [Route("api/{controller}/{name}/{id}")]
    public string GetItemByNameAndId(string name, int id)
    {
         // Find item here ...

         return item.ToString();
    }

}

http://192.112.183.42:80/api/platypusItems/DuckbilledPlatypisAreGuysToo/42 will be mapped to GetItemByNameAndId while http://192.112.183.42:80/api/platypusItems/42 will be mapped to GetItemById.

Note, that you need to enable attribute routing in configuration like this:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();

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

But generally you should pass arguments as additional parameters. It is especially easy with GET requests. This will work in Web API 1&2:

public class ItemsController : ApiController
{
    public string GetItemById(int id)
    {
         // Find item here ...

         return item.ToString();
    }

    public string GetItemByNameAndId(string name, int id)
    {
         // Find item here ...

         return item.ToString();
    }
}

Assuming that you have default mapping configuration, http://192.112.183.42:80/api/platypusItems/42 will be mapped to GetItemById while http://192.112.183.42:80/api/platypusItems/42?name=DuckbilledPlatypisAreGuysToo will be mapped to GetItemByNameAndId because Web API can map 2 parameters instead of 1 for GetItemById.

More information can be found in Mike Wasson articles on Attribute Routing, Routing and Action Selection and Routing in Web API.