1

I have a RESTful Web API built using the ASP.NET MVC template. It's working nicely. I'm unsure how to elegantly arrange two methods with conflicting parameters. I have a Certifications table that lists my Microsoft certifications. I have an Exams table that lists the exams for each certification. There is a one-to-many relationship. When I created the ExamsController it automatically added a GetExams() method and a GetExam(int id) method. The GetExams method returns all the Exams records, the GetExam method returns the Exam record that matches id. So far so good. I wanted to add a GetExams(int certificationId) method to return all of the exams that relate to a specified certification. That's when the train left the tracks. It threw an error that there were conflicting methods which doesn't make sense to me because one is named GetExam with an int parameter and the other is named GetExams with an int parameter. (I think Microsoft has some design issues to improve in a future release of Web API). So I re-wrote the second method to be GetExams(int id, int extra) and I ignore the extra int parameter. It works, but it's not elegant, and I'm an elegant kind of guy. What is the best RESTful way of organizing these three methods?

Steve Gaines
  • 571
  • 1
  • 6
  • 22
  • What are the URLs to obtain the two resources? – Jasen May 12 '16 at 21:24
  • To get one Exam: http://stevegaines.info/api/Exams/4, to get all the Exams for CertificationID 3: http://stevegaines.info/api/Exams?id=3&extra=0 – Steve Gaines May 12 '16 at 21:38
  • 2
    Create a new Action `IHttpActionResult GetExamsByCertification(int certificationId)` and map it to a route like `api/Certifications/{certificationId:int}/Exams` – Nkosi May 12 '16 at 21:46
  • Nkosi, that's a structure I would not have guessed, but it makes sense. Is that the standard way of doing this in RESTful or is that just your way? I'm new to RESTful services. – Steve Gaines May 12 '16 at 22:16
  • Nkosi - I tried to code what you suggested and it gave me "HTTP Error 404.0 - Not Found". Do I need to add a routing path in WebApiConfig.cs? What would that look like? I also tried another suggestion I found online online to add something like public IQueryable GetExams([FromODataUri] int key) and call it with api/Certifications(3)/Exams but that failed with "No HTTP resource was found that matches the request URI". Can anyone suggest the solution? – Steve Gaines May 13 '16 at 02:12

1 Answers1

4

Fix your URLs and use Attribute Routing

[HttpGet]
[Route("api/exams/{id}")]
public IHttpActionResult GetExams(int id) { }

[HttpGet]
[Route("api/certifications/{cid}/exams")]
public IHttpActionResult GetCertificationExams(int cid) { }
Jasen
  • 13,170
  • 3
  • 43
  • 64
  • Jasen - That worked. Thank you very much. I didn't try it for a few hours because I didn't think it would work, but I don't know a lot about Web API yet. I've read several MSDN (and other) explanations of Web API routing but haven't found a clear, succinct explanation yet. Is there one you like? I thought it would need an "s" at the end of Certification. Is this a normal RESTful solution to querying related entities? That is, using the Attribute Routing? Any explanatory link would be appreciated. – Steve Gaines May 13 '16 at 03:52
  • 1
    It is [hard to find a clear, succinct explanation](http://stackoverflow.com/questions/671118/what-exactly-is-restful-programming). Here is some basics on Attribute Routing http://stackoverflow.com/questions/671118/what-exactly-is-restful-programming. – Jasen May 13 '16 at 18:26
  • 1
    Attribute Routing is nice because I can immediately see which URL will match my action and frees you from the convention rules to name your actions whatever makes most sense to you. – Jasen May 13 '16 at 18:37