Generating API documentation
Out of the box API help
The WebAPI supports generation of a help page featuring descriptions of each controller / Http method etc. - even generated samples - I found this blog useful to understand the process, including a nice video - and the feature has come a long way since it was first introduced.
For a green-fields application I would strongly recommend using it!
Here's one I prepared earlier...
However, for Enterprise Tester we already had an existing in-application help system in place, and so decided to also put our generated API documentation there as well.
Here's what the help system looks like:
We did initially look at harnessing what came out of the box with WebAPI, but decided given the way our JSON rewriting works, and some of our additional metadata such as expansions, that it would be easier to implement much of what we needed from scratch.
To do this we opted for a more localized approach - marking controllers and action methods up with attributes to provide the metadata to generate the documentation - this also provides a hint about the Expands it supports etc.
[HttpMethodInfo(
Description = "Retrieves all (or a subset) of automated tests that are visible to the current user.",
RequiredPermissions = new[] {CoreOperations.CoreOperationsTestManagementView.FullName},
SupportsTQL = true)]
[HttpMethodSupportsStatusCode(HttpStatusCode.OK, "....description...")]
[HttpMethodSupportsStatusCode(HttpStatusCode.Forbidden, "....description...")]
[ExpandInfo(typeof (AutomatedTest), typeof (ViewAutomatedTestModel))]
public HttpResponseMessage Get(string tql = null)
{
...
}
Next, we wanted to provide multiple examples for each HTTP method - we did this by setting up a class called "ExampleInfo":
public class ExampleInfo
{
public string Method { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public ListRequestHeaders { get; set; }
public ListResponseHeaders { get; set; }
public ListRequestParameters { get; set; }
public object RequestModel { get; set; }
public string RenderedRequest { get; set; }
public object ResponseModel { get; set; }
public string RenderedResponse { get; set; }
public HttpStatusCode ResponseStatus { get; set; }
}public class ParameterInfo
{
public string Key { get; set; }
public string Value { get; set; }
public string Description { get; set; }
}
And then controllers (or their abstract base controllers...) could provide examples by implementation a static method on the controller itself i.e.
static IEnumerableGetPostExamples()
{
yield return new ExampleInfo { .... };
}
The name of the method is not important, we match only on type signature (so you can have as many example methods as you like i.e. one per HTTP method etc.)
Also notice that in the example info we have both a ResponseModel and a RenderedResponse properties (and equivalents for the request) - rendered requests (strings) are useful when providing examples for documenting multi-part mime supporting methods, but primarily we leveraged the RequestModel/ResponseModel which meant changes to examples would always reflect the current codebase.
Resource documentation
Given all this information we then generate a help topic that looks like this:
In addition we generate a index list of all available resources, providing a quick overview of what methods are support by each resource.
For collection resources, where the results can be filtered (either by filtering via OData's $filter query parameter, or via TQL - Testing Query Language) we also include a small label indicating which query type is supported.
Last of all (an arguably one of the most useful views for a developer building an API) is the permission view - though you should obviously have tests to verify the authorization restrictions applied to each method, it can be very useful to see it presented in a matrix view - so for each resource, we can see what permissions are required.
Because of the underlying help system it's possible for 3rd party developers to further extend the content of these help topics or add new topics to further document the capabilities of the API.
Bulk Actions
Last of all beyond REST we also expose some existing functionality via JSON RPC, such as support for bulk actions.
Bulk actions within the application take a set of items (or a query returning a set of items) and then applies an action to that set - be it generating some form of Export, performing a bulk move/update/delete etc.
We contemplated trying to translate these concepts into a RESTful context, but it didn't really make sense and so instead opted for a mechanism to start these background tasks, and then monitor their progress.
Metadata related to bulk actions was already available via the IoC container, so we implemented some additional help topic "providers" to generate additional topics necessary for examples of the various types of action you could execute through the API.
Next
Next in part 4 we take a look at OData, TQL and filtering of collection resources.