11

I'm looking at developing an application in ASP.NET MVC 3 and would like to provide a public API at the same time.

From looking around, there seems to be 2 ways to go about it. Either create an API area and have controllers that return json / xml. Or use action filters and a single front end set of controllers, and have those return json / xml / html depending on the request headers.

I'd like to do the later, but I was wondering how you could go about versioning your api if you went this route?

If you go the first route, you could easily just create a v1 / v2 controller, but if you do the later, how could you version it?

Matt Brailsford
  • 2,209
  • 3
  • 28
  • 40

2 Answers2

12

Versioning is a rather complex issue to begin with. Here are ways I looked at before:

  1. URL. In this case https://api.example.com/v1/projects is assumed to be a different resource than http://api.example.com/v2/projects, even though its not the case. Basecamp seems to do this. Following this approach, assume you'll always have to support old APIs.
  2. Headers. The URLs remains the same, however, the client pass an additional HTTP header, say X-MYAPI-VERSION with each request with a value identifying the version of the API to use. The Google Documents List API do this. A potential problem with this approach is that HTTP headers may be stripped by intermediaries between the client and server.
  3. Parameters. To circumvent the problem with option 2, you can pass the API version to use as a parameter (such as https://api.example.com/projects?v=3).
  4. Media types. Here your URLs stay the same, however, users are required to specify the representation of the resources using the accept and content type headers. For example, a "project" can be presented using "application/vnd.mycompany.resource[-version][+format]" giving your representations of "application/vnd.mycompany.project-v1+json" for v1 json or "application/vnd.mycompany.project-v1+xml" for v1 xml. When you need a new version of a project comes along the mime type may look as follows "application/vnd.mycompany.project-v2+xml". Github seems to support that.
  5. Part of payload. In this case the payload of the request contains the version number to use. For example, when XML is passed, you can look at the namespace to determine which version of the API is being used. For JSON, you can use a "$version" or "_version" property to specify the version.
  6. Client Key. When the application is registered, it specifies which version of the API it wants to use. When you authenticate the client, you ensure that you emulate the version it wants to use.
  7. No explicit versioning There is always the option not to version your API and try to handle changes transparently by making all fields optional and handle them appropriately when they are missing. Chances are you will be doing this anyways to make future versions of your API compatible with the version you are developing today.

Many recommend option 4, although its not always practical. Most of these options require additional work to get working with ASP.NET MVC.

bloudraak
  • 5,902
  • 5
  • 37
  • 52
  • 2
    If you are interested in approach #1 (my preference), then check out this NuGet package and the correspond code/examples on GitHub : https://www.nuget.org/packages/VersionedRestApi/1.0.0.2 – jakejgordon Nov 07 '15 at 15:05
  • For approach #2 (my preference), User-Agent would be the right header for this approach (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43). "The field can contain multiple product tokens (section 3.8) and comments identifying the agent and any subproducts which form a significant part of the user agent" Example would be: User-Agent: YOUR_API_ID/2.0 – Fabian Köbel Nov 18 '15 at 15:29
  • 1
    I don't agree with using the User-Agent to version APIs. The spec refers to the client product. For example, the browser that is connecting to the HTTP server. It has far more benefit when the application developer of the client uses the User-Agent to specify their client, so that we can track API usage from a client perspective. Very useful when AppX/1.1 fails on some calls to MyAPI v1.1, but AppX/1.2 doesn't. You'll loose that kind of tracking. – bloudraak Dec 06 '15 at 05:54
3

You can go one of two routes - you can include the API in the route (instead of http://app.lication/category/1 you would have something like http://app.lication/api/v1/category/1) or you could include a custom HTTP header.

Either will allow you to discriminate which version's being called.

Community
  • 1
  • 1
48klocs
  • 6,073
  • 3
  • 27
  • 34
  • Regarding option 1 - can you elaborate? It's not obvious how to do that when doing what the OP wants to do - a single set of controllers that returns json/xml/html depending on the request headers. Since presumably he doesn't want the `/v1` in his html urls. – Gabe Moothart Feb 08 '12 at 17:12
  • @GabeMoothart - you'd use ASP.Net Routing (http://msdn.microsoft.com/en-us/library/cc668201.aspx) to define/extract URL parameters. Making the API part of the path doesn't mean you need to have a controller per API (nor does it preclude it, if the APIs are radically divergent). – 48klocs Feb 08 '12 at 18:21