Recently, we showcased a Utility Network web app sample written in TypeScript. Behind the scenes, we had created our own SDK or client in TypeScript. Let’s take a step back though, at present, there are three Utility Network SDK options for development and integration (1) the ArcGIS Pro .NET SDK, (2) Geoprocessing/Python tools and (3) the REST web service.
If developing with Utility Network in ArcGIS Pro, you have a full-featured SDK and Geoprocessing tools to get the job done. If developing for something else – say a web app or an administrative console app, your gateway is through the Utility Network REST service.
Interacting with REST services is typically pretty straightforward, it’s usually the “plumbing,” or the supporting infrastructure, that can take the longest to code. Code to support the packaging, execution and processing of REST methods can easily grow into 1000’s or 10,000’s of lines of code.
In this post, we will walk through tools and technology that can accelerate REST client development by creating the plumbing code for you. Also, the plumbing can be created in your language of choice on your platform of choice (TypeScript, Python, C++; Apple, Windows, so on).
We’ll use the Utility Network service as an example, and specifically Utility Network’s trace REST endpoint or method.
Swagger.
You might be familiar with WSDL (Web Service Description Language) of SOAP fame. There are also REST equivalents RAML, WADL, YAML some are holding on, but most have come and gone.
Swagger, about eight years old now, continues to gain traction and is now more formerly known as the “OpenAPI Specification,” but we’ll stick with the Swagger moniker here because it’s swanky.
Swagger a specification and language provide the ability to describe a REST service contract in common terms. Once expressed in Swagger, the API contract is human and machine readable, the web service’s makeup and capabilities documented and known.
Swagger is a simple language, but like all languages, it has syntax rules to adhere to and a general structure to follow.
Editing Swagger by hand is possible, but a user interface even better with built-in linting and syntax checking. Restlet Studio is an easy to use and full-featured interface making writing Swagger a breeze. There is a free version that has many paid features, but limits use to one API only.
Raw Swagger, Restlet Studio side by side
Defining Utility Network REST endpoints
The Utility Network interface documentation outlines the trace method. Incidentally, the trace endpoint is also the biggest, most complex, endpoint of the lot for Utility Network REST interface.
Trace by the numbers:
- 33 parameters total
- 31 parameters are optional; this turns out to be important
- 22 sub-parameters in traceConfiguration parameter
The process to define the service in Swagger terms is straightforward.
- Create a service name
- Add endpoints
- Add verbs (GET, PUT, POST)
- Add request parameters (body, query parameters)
- Add response parameters (body)
- Ship it!
Though there is a common language, the service can be described differently through different data constructs, or objects. These objects can hold parameters or request bodies and break down very large types into smaller, more manageable, objects or types.
Swagger to Code
Now equipped with a Swagger specification, it’s time to generate a client library.
There are many open-source tools and programs available on the web, two of the more popular are the powerful console engine swagger-codegen and nSwagStudio.
The nSwagStudio generator supports C#, TypeScript clients. It has an installer, provides a user interface and has several options to customize the generated output code. The swagger-codegen framework has good community support with over 40 different contributions to generators for Python, C++, Objective-C it also has more steps to set up.
This example uses nSwagStudio. Our Github repo has this example and samples of other clients generated using swagger-codegen to try out.
The process to generate couldn’t be easier.
- Use a GitHub path to pull the Swagger.json from
- Select the C# Client options
- Click “Generate Output” button
- C# code generated in the output window (or you can specify a file to save it to)
There are a good many options in the settings to customize generated output, but to keep it simple we’ve taken all defaults.
In all, this generated a 2500+ line client! There are a few tweaks necessary to make the output work; we’ll step through that next.
Client Run
Initial runs with a Swagger generated C# client hit a snag with “optional” parameters. As mentioned earlier, Utility Network documentation has most parameters and properties as “optional.”
What is “optional?” Thought I knew, turns out I didn’t.
“Optional” means different things based on context. In the context, of the Utility Network trace method, it means that the value for a parameter may or may not be specified (i.e. “”), but the property or parameter itself should be there.
In the context of Swagger and interpreting it in a code generator, a parameter marked as “optional” is a parameter that can be left out of the call entirely. When it is not in the call body, trace fails with a nebulous error message, but more importantly, it didn’t work.
As much fun as it could be, we’ll table the deeply philosophical question about what “optional” should or shouldn’t mean and specify a default value for the “optional” parameters. A quick search-and-replace of the strings in the generated code with an empty string (““) and all is good (did try an empty string as default value, that didn’t work).
Wrapping Up
As the Utility Network creates opportunities for integration through web services, a Swagger definition can help quickly build out a support framework through native clients.
The Swagger definition used here, generated code, and sample project are up on SSP’s Github. Also, there are samples of code trace API code generated by swagger-codegen including C++, Akka-Scala, Python, TypeScript-Angular, and TypeScript-Node. Caveat Emptor: those clients are untested.
Try it out, and if you do, share your experience.
What do you think?