Monday, September 28, 2015

Easily expose metadata information from Web API

A client recently asked me for something in their Web API project that I'd never done before - they needed a way to expose metadata information about a few specific response objects that were being returned by the API. It sounded like it would be an easy task, but after spending a couple of hours at the Googler, I really didn't find any examples on that specific topic using the description above.

I was fortunate to eventually stumble across a good start to the solution nested within this article on OData basics while investigating a completely unrelated topic. Seeing as it was kind of challenging for me to find, I thought I'd take the time to document it. Before I launch into the solution though, I just want to clarify one point - I did not want to build OData routes in the API for this project. I simply want to expose metadata information for some of the existing response objects it was already providing.

With that being said, here's what I came up with to meet the request:

Part 1 - Modify the WebApiConfig.cs file to include "routes" for each object for which you want to expose metadata information.

This actually turned out to be easier than I had anticipated ... once I'd found a solution in the above article. It only required adding about half a dozen lines of code to the WebApiConfig.cs file to create an EDMX model builder function and define which objects to pass through it:

Simple as that; metadata routes are now available. So now that I had the routes I needed, how could I let requesters know that metadata information about the response objects is available, and where they could go to find it? Why, add the new metadata URLs to the response objects, of course!

Part 2 - Create a Controller to represent the metadata routes and use Hyprlinkr to expose them.

Create a new Controller in your project, and name it using whatever URI you used in the WebApiConfig declarations you added in Step 1 (in my case, this would be "EntitiesController"). It is very important that you keep the name the same here. You do not need to modify this file at all; it's simply an anchor for the dynamic links we're going to be creating with Hyprlinkr.

As stated on the Hyprlinkr project's GitHub page, "... it creates URIs according to the application's route configuration in a type-safe manner.". This little guy is great for dynamically discovering URIs that can be sent back as string properties of the response objects. This means regardless of which environment or location you deploy to (dev, prod, test, cloud, etc.), the metadata URIs will always be correct - HyprLinkr will discover them for you automatically.

There are two remaining steps to complete for each of your response objects:

  1. Add a property to your response object to store the metadata URI. I went literal and called mine "metadataUri", but feel free to name it however you see fit.
  2. Add code wherever you're building your response objects to populate the new field. Hyprlinkr makes this easy; it's just one extra line:
    SomeClass.metadataUri = (
    this.Url.GetLink(x => x.Get()).ToString() + "/SomeClass/$metadata"
    );

Not a very straightforward solution, but I'm really happy with the result, and will definitely be able to reuse the idea for future API projects. I think it's a nice & simple addition to the documentation for any public-facing API.