MartinM MartinM -3 years ago 72
C# Question

Routing multiple GET methods from same controller - Web Api

I'm currently having a problem with a Web Api I'm working on.

I have a controller with two Get methods. one which returns a list of objects. the other which returns a list of the same object, but filtered based on some parameters that are passed in. Like so:

public IList<MyObject> Get(int id)
{
//Code here looks up data, for that Id
}

public IList<MyObject> Get(int id, string filterData1, string filterData2)
{
//code here looks up the same data, but filters it based on 'filterData1' and 'filterData2'
}


I cannot make the routes work for this. Especially as the Api help page seems to display the same url multiple times.

my routes look like:

config.Routes.MapHttpRoute(
name: "FilterRoute",
routeTemplate: "api/Mycontroller/{Id}/{filterData1}/{filterData2}",
defaults: new { controller = "Mycontroller" }
);

config.Routes.MapHttpRoute(
name: "normalRoute",
routeTemplate: "api/Mycontroller/{Id}",
defaults: new { controller = "Mycontroller" }
);


Anyone know?

Also, is it possible to change my filtered method to something like

public IList<MyObject> Get(int Id, FilterDataObject filterData)
{
//code here
}


Or can you not pass complex objects on a Get?

Answer Source

Lets say you have the following route:

routes.MapHttpRoute(
    name: "Default", 
    routeTemplate: "api/{controller}/{id}/{p1}/{p2}",
    defaults: new { id = RouteParameter.Optional, p1 = RouteParameter.Optional, p2 = RouteParameter.Optional });

GET api/controller?p1=100 map to public HttpResponseMessage Get(int p1) {}

GET api/controller/1?p1=100 map to public HttpResponseMessage Get(int id, int p1) {}

GET api/controller/1 map to public HttpResponseMessage Get(int id) {}

and so on...

GET and complex model bind: by definition a complex model should be in the request body (verb independent) (a url contains a length limitation that can broke complex models). You can force the WebApi to look for the complex model in the URL by doing:

routes.MapHttpRoute(
    name: "Default", 
    routeTemplate: "api/{controller}/{customer}");

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public HttpResponseMessage Get([FromUri] Customer customer) {};

GET api/customers?id=1&name=Some+name

Just a note: GET with complex types, most of the time (like my example) makes no sense. Why should you get a customer by id and name? By definition a complex type expects a POST (CREATE) or a PUT (UPDATE).

To call with subfolders structure, try:

routes.MapHttpRoute(
    "MyRoute",
    "api/{controller}/{id}/{p1}/{p2}",
    new { id = UrlParameter.Optional, p1 = UrlParameter.Optional, p2 = UrlParameter.Optional, Action = "Get"});

GET /api/controller/2134324/123213/31232312

public HttpResponseMessage Get(int id, int p1, int p2) {};
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download