Blogtronica

Thoughts, ramblings and insights

netronica.io

Autorest, another nail in the WCF coffin

I have been using Swagger as a mechanism to self document the APIs that I have built for a while now, if you haven't heard of Swagger then stop, and check it out! for dotnet there is Swashbuckle. TL;DR; It is, it scans your Web-API routes and generates a json schema that describes all the POSTs, GETs, PUTs etc. With Swashbuckle you can browse to /swagger and interact with your API in the browser. Like this: http://petstore.swagger.io/

The second half of the equation is consuming the APIs. This is where Autorest comes into play. It is written by Microsoft and is used by their Azure management APIs.

I have been looking for an excuse to use it for a while now, and it worked really well.

You install it either via nuget or chocolatey. To generate your files you simply run

AutoRest.exe -CodeGenerator CSharp -Modeler Swagger -Input swagger.json -Namespace MyNamespace  

There were a few gotchas to be aware off...

You might be tempted to document your error conditions with swagger. i.e.

[SwaggerResponse(HttpStatusCode.OK, "Populated response" , typeof(MyResponse))]
[SwaggerResponse(HttpStatusCode.BadRequest,"Invalid parameter"]
public HttpResponseMessage MyGet(string countryCode)  
{

The problem is that autorest now interprets BadRequest (400) as an empty response

var myClient = new MyClient();  
MyResponse response = myClient.MyGet("Invalid");  
//Returns a null

How about returning a custom error object? i.e.

[SwaggerResponse(HttpStatusCode.BadRequest,"Invalid parameter",typeof(MyError)]

As a result, object is the only common polymorphic type. And Autorest generates:

object response = myClient.MyGet("Invalid");  
//myClient.MyGet now returns type object 

If you do want the Autorest client to throw an exception for all errors, you need to remove the swagger response documentation for them, either from the source, or by first parsing the json output before calling Autorest.

If you're interested in sending and receiving HTTP headers, there is another way of consuming the API calls.

HttpOperationResponse<MyResponse> response = myClient.MyGetWithHttpMessages("GB");  
//response.Body will be your deserialised MyResponse
//response.Request will contain the HttpRequest
//response.Response will contain the HttpResponse

By the way, if you're just looking for once-off client generation, perhaps you're consuming someone else's API with a swagger contract, you can always use an online swagger schema-to-code generator such as http://editor.swagger.io/#/

Photo credit. https://www.flickr.com/photos/crd/3883561986