Tag Archives: WebAPI

Extending your WebAPI documentation

As I already mentioned in a previous post, you can use the Microsoft.AspNet.WebApi.HelpPage NuGet package to generate a human-friendly documentation for your WebAPI directly from your source code. Because the NuGet package installs its full source code, you can customize the generated help pages with a few simple steps.

For example lets assume you designed your API that in case of any error all actions return an error code with the associated error message, and you store the possible errors in a different enum for every action. And of course you want to display these error cases in you API documentation!

Using a custom attribute – which I call here ErrorCodeType – you can connect the error code enum (here MyErrorCodeEnum) to the action on metadata level:

[ErrorCodeType(typeof(MyErrorCodeEnum))]

To display this information on the help pages, follow these steps:

 

1. Create a new class which will describe a single error case. Let’s call it ErrorCodeDescription and place it into the Models folder:

public class ErrorCodeDescription
{
  public int Code { get; set; }
  public string Message { get; set; }
}

 

2. The HelpPageApiModel.cs file contains the view-model which carries the data for the help page. Add a new property to this class which will contain all error cases in a list:

public List<ErrorCodeDescription> ErrorResponses { get; set; }

 

3. The GenerateApiModel method in the HelpPageConfigurationExtensions.cs file is responsible to build the view-model. You can find the VM in the apiModel variable which has the GenerateApiModel type. Here you can create and call a new custom method which retrieves your custom attribute and builds the ErrorResponses list like this:

private static void GenerateErrorResponses(HelpPageApiModel apiModel)
{
  ErrorCodeTypeAttribute attribute = apiModel.ApiDescription.ActionDescriptor
    .GetCustomAttributes<ErrorCodeTypeAttribute>().FirstOrDefault();
  Type enumType = attribute.ErrorCodeEnumType;
  string[] names = Enum.GetNames(attribute.ErrorCodeEnumType);

  foreach (string name in names)
  {
    apiModel.ErrorResponses.Add(new ErrorCodeDescription
    {
      Code = (int) Enum.Parse(enumType, name),
      Message = "TODO"
    });
  }
}

 

4. The Views/Help/DisplayTemplates/HelpPageApiModel.cshtml view is responsible for rendering the view-model. Add the following block to the view which delegates the rendering of the ErrorResponses list to the ErrorResponses partial view:

@if (Model.ErrorResponses.Any()) 
{ 
  <h3>Error Responses</h3> 
  @Html.DisplayFor(m => m.ErrorResponses, "ErrorResponses") 
}

 

5. Finally you have to create the ErrorResponses.cshtml file in the same folder. This partial view will receive a List<ErrorCodeDescription> instance as its @model and it is totally up to you how you want to transform it to a human-friendly HTML page.

 

At first it may seem too complicated, but in reality the steps are very logical and totally worth the time understanding it.

 

Technorati-címkék: ,

JSON or not JSON: that is the question

When you write unit tests for a REST API, you probably want to test whether the given response is in the expected format. For example you want to ensure, that the response string is a valid JSON or not.

You can find a very simple tip on StackOverflow and in other blogs as well: just check whether the first character of the response is a < or { character, because JSON is about Object Notation, right? The problem with this approach is not only that it does not perform a thorough analysis, but also that its basic statement is simply not true. According to json.org, a JSON can also contain only a single value, the specification does not require it to be an object or an array at all:

json-value

So I love JSON, 123, true and false are all valid JSON strings.

Unfortunately I could not find a simple IsValidJson method, but I could come up with this solution using Newtonsoft JSON.NET library:

try
{
    JToken.Parse(input);
    return true;
}
catch (JsonReaderException)
{
    return false;
}

Is there a better solution?

 

Technorati-címkék: ,,