1

I'm in the process of designing a RESTful Web API and have bumped into the following problem: I need a controller to retrieve collections (called Sections) of a hierarchical structure as well as to retrieve a single part (a single Section). If I need a collection I have to refer to the ID of the root Section which gives me a subtree of the whole structure. So I went ahead and defined a SectionsController like this:

public class SectionsController : ApiController
{
  // GET api/sections/5
  // Gets a subtree.
  public IEnumerable<Section> Get(int rootId)
  {
     ...
  }

  // GET api/sections/5
  // Gets a single section.
  public Section Get(int sectionId)
  {
     ...
  }

Which obviously doesn't work as the signatures are identical. What is the recommended way to go about this?

Thorsten Westheider
  • 10,572
  • 14
  • 55
  • 97
  • 1
    Put them in different controllers, or give them more specific names. Such as `GetSectionsWithRoot` – Rob Dec 14 '15 at 08:32
  • 1
    I thought about putting them in different controllers. As for the second suggestion, wouldn't that violate REST? I'd like to end up with URIs as api/sections (GET) and api/sections/5 (GET), so api/subsections/5 would be perfectly fine I guess. Not sure what GetSectionsWithRoot would lead to. – Thorsten Westheider Dec 14 '15 at 08:38
  • I suppose it does violate rest, but not all APIs strictly adhere to the REST guidelines :). In any case, you could write `/api/hierarchy/5`. Edit; or yes, /subsections/ works too – Rob Dec 14 '15 at 08:41

2 Answers2

3

If you want to follow standard REST patterns you should introduce a slightly different API:

public class SectionsController : ApiController
{
  // GET api/section
  public IEnumerable<Section> GetAll()
  {
     ...
  }

  // GET api/section/5
  public Section Get(int sectionId)
  {
     ...
  }

Normally you should use singular resources and provide identifier only for a specific one. You can't have same URLs, even with different controllers.

kamil-mrzyglod
  • 4,948
  • 1
  • 20
  • 29
0

Reading this post on SO regarding image transfer and following the link provided I realized there is a very simple solution to this problem that respects REST and at the same time doesn't require additional controllers.

Just return a collection of the subtree IDs within the object requested for a particular ID, i.e.

public class Section
{
   public int Id { get; set; }
   public string Name { get; set; }
   public int[] DescendantIds { get; set; }
}

So with a single call to

api/section/5

I get all the details for the section with ID 5 as well as the IDs of the sections below. Yes, there's some overhead involved, so you have to decide for yourself if this solution is for you.

Community
  • 1
  • 1
Thorsten Westheider
  • 10,572
  • 14
  • 55
  • 97