Reputation: 52725
I'm creating the following controller:
public FoosController : ApiController
{
public IQueryable Get()
{
return AnODataQueryableListOfFoos();
}
public void Delete(Guid id)
{
DeleteTheFooWithId(id);
}
public IQueryable<Bar> GetBars(Guid id)
{
var foo = GetFooById(id);
return AnODataQueryableListOfBarsForThisFoo(foo);
}
public IEnumerable ProjectedBars(Guid id)
{
var foo = GetFooById(id);
return foo.Qux
? OneProjectionOfBars(foo)
: AnotherProjectionOfBars(foo);
}
}
(a list of Bars can be thought of as the "content" of Foo...)
It was my intention to use the following URLs:
GET /api/Foos -> Get
GET /api/Foos/SOME_GUID/Bars -> GetBars
GET /api/Foos/SOME_GUID/ProjectedBars -> GetProjectedBars
DELETE /api/Foos/SOME_GUID -> Delete
I tried with a couple of combinations of [ActionName]
and custom routes, but there was always either a conflict or a 404.
What is the easiest way to get this working? I'd like to keep my routes generic (i.e. no controller-specific stuff) if possible. Other controllers use a more standard /Stuff
- Stuff/id
approach.
I'm also open to someone pointing out I'm completely misusing URLs. Improvements welcome.
Upvotes: 3
Views: 62
Reputation: 4978
I agree that Attribute Routing would be the best way to go, however you could try the following:
public FoosController : ApiController
{
[HttpGet]
public IQueryable Get()
{
return AnODataQueryableListOfFoos();
}
[HttpGet]
[ActionName("Bars")]
public IQueryable<Bar> GetBars(Guid id)
{
var foo = GetFooById(id);
return AnODataQueryableListOfBarsForThisFoo(foo);
}
[HttpGet]
[ActionName("ProjectedBars")]
public IEnumerable GetProjectedBars(Guid id)
{
var foo = GetFooById(id);
return foo.Qux
? OneProjectionOfBars(foo)
: AnotherProjectionOfBars(foo);
}
}
and then use the following routes:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi2",
routeTemplate: "api/{controller}/{id}/{action}"
);
Upvotes: 2
Reputation: 25732
What you're asking for is n-depth sub-resources and the only real solution to this is the attribute routing provided in v2 of the Web API. Until it is released (which I believe will be soon), you can use RPC like approach:
routes.MapHttpRoute("RPC", "rpc/{controller}/{id}/{action}");
You'll need to register this as the very first HTTP route, and use a prefix other than 'api' so it won't clash with the actual api/ routes.
Upvotes: 0