ASP.NET Web API Help Page Part 2: Providing custom samples on the Help Page

Samples in ASP.NET Web API Help Page are automatically generated based on your action parameters and return types. They represent the kind of contents that could go into the request or response body. For instance, if you have the Delete action inside ValuesController like below: 

 public class ValuesController : ApiController
 {
     public void Delete(CompositeValue param);
 }
  
 public class CompositeValue
 {
     public int Id { get; set; }
     public string Name { get; set; }
     public DateTime Date { get; set; }
 }

The help page would give you the following samples:

image

Understanding how samples are generated

Before we get into customization, it’s worth understanding how these samples are generated. For starters, it uses ApiExplorer to figure out the body parameter type and the return type of you action. Then it will try to create an instance of these types with dummy data. Finally, it ask ApiExplorer for the appropriate formatters to write the created instance into the sample string.

Now that you understand how the samples are generated, there shouldn’t be any surprise when you see something like “Failed to generate the sample for media type 'application/x-www-form-urlencoded'” on the help page:

image

Yes, that’s because the default JQueryMvcFormUrlEncodedFormatter doesn’t support writing. However, you can still make it work by setting custom samples.

Setting custom samples

Most of the help page customizations can be done in HelpPageConfig.cs. If you open the file, you’ll see a bunch of commented codes that show you different ways of providing custom samples to the help page.

image

One way of solving the problem described above is by using SetSampleForType, which allow you to set the sample string directly. For instance, setting the following will have the help page display “Id=123&Name=Foo&Date=2012-10-13” as the application/x-www-form-urlencoded sample for actions with CompositeValue.

 config.SetSampleForType(
     "Id=123&Name=Foo&Date=2012-10-13", 
     new MediaTypeHeaderValue("application/x-www-form-urlencoded"), 
     typeof(CompositeValue));

And there’re other ways of customizing the samples that you can explore on your own:

 // Uncomment the following to use "sample string" as the sample for all actions that have string as the body parameter or return type.
 // Also, the string arrays will be used for IEnumerable<string>. The sample objects will be serialized into different media type 
 // formats by the available formatters.
 config.SetSampleObjects(new Dictionary<Type, object>
 {
     {typeof(string), "sample string"},
     {typeof(IEnumerable<string>), new string[]{"sample 1", "sample 2"}}
 });
  
 // Uncomment the following to use "1234" directly as the request sample for media type "text/plain" on the controller named "Values" 
 // and action named "Put".
 config.SetSampleRequest("1234", new MediaTypeHeaderValue("text/plain"), "Values", "Put");
  
 // Uncomment the following to use the image on "../images/aspNetHome.png" directly as the response sample for media type "image/png"
 // on the controller named "Values" and action named "Get" with parameter "id".
 config.SetSampleResponse(new ImageSample("../images/aspNetHome.png"), new MediaTypeHeaderValue("image/png"), "Values", "Get", "id");

 

Setting the samples when the action returns an HttpResponseMessage

When the action returns an HttpResponseMessage, the content of the response body becomes unpredictable based on the signature. Therefore, by default the help page simply doesn’t know what sample to display. However, you easily customize it to show the right sample.

Consider the following two scenarios where you return an HttpResponseMessage:

HttpResponseMessage with content negotiation

This is when your action supports content negotiation. Something like below:

 public HttpResponseMessage Post()
 {
     var returnValue = new CompositeValue { Id = 1, Name = "Foo", Date = DateTime.Now };
     var response = Request.CreateResponse<CompositeValue>(HttpStatusCode.Created, returnValue);
     response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = returnValue.Id }));
     return response;
 }

Here you simply need to use SetActualResponseType to indicate the actual type that goes into the body of the HttpResponseMessage. You can set this in the HelpPageConfig.cs:

 config.SetActualResponseType(typeof(CompositeValue), "Values", "Post");

As a result, the help page would now display the right samples for the Post action above.

image

 

HttpResponseMessage without content negotiation

This is when you’re returning the HttpResponseMessage without the content negotiation. Something like the following where the content is simply a StringContent.

 [AcceptVerbs("Custom")]
 public HttpResponseMessage Custom()
 {
     return new HttpResponseMessage
     {
         Content = new StringContent("action completed.")
     };
 }

Here you can simply control what sample to display for the action by using SetSampleResponse:

 config.SetSampleResponse("action completed.", new MediaTypeHeaderValue("text/plain"), "Values", "Custom");

This will have the help page display the following sample for the Custom action above.

image 

 

Related blog posts

ASP.NET Web API Help Page Part 1: Basic Help Page customizations

ASP.NET Web API Help Page Part 3: Advanced Help Page customizations