Expanding your RESTful architecture with ArcGIS Server
Author's Note: After I originally posted this write up, I got a good comment from Sean Gillies (see comments to this post) with a couple important notes in it. First, I let SOAP and WS-* terminology bleed into my discussion of REST when I referred to a "REST endpoint". Once it's RESTful, it's a resource, not an endpoint. In addition, he called attention to an error in the example REST URI I provided (http://mywebsite/roadPoints/create). Since we're not creating a new state on the server side, the correct request is a GET. See Sean's comment for more info. Sorry for the errors in the original post.
During the ESRI Developer Summit last week, Dave and I both talked about some principles and methodologies in a RESTful architecture that we've used in several scenarios here at DTS, when the use of the ESRI-provided ArcGIS Server REST API either doesn't offer the functionality needed to accomplish a required function, or the REST API is not optimal in accomplishing that function.
What you can't do, and what you can do better
When we look at the functionalities exposed by the various ArcGIS Server-side APIs, we see a trend that looks something like the following diagram. The SOAP API offers a subset (albeit a very large one) of the aggregate functionality offered by ArcGIS Server, while the REST API offers a subset (and still a pretty impressive one) of the functionality exposed by the SOAP API. (FWIW there was some chatter at the dev summit that the REST API would eventually be functionally equivalent to the SOAP API.) Not surprisingly there are simply some things you cannot do via the REST API and since our preferred approach is to access ArcGIS Server via the REST API whenever possible, we frequently need an alternate solution. In addition, consider the following scenario: As a developer, I need to implement functions that allow the user to locate a point along a linear feature by "click" on the map with a minimum of friction. The actual GIS of our theoretical operation might look something like this:- Take a user specified point and buffer it
- Reproject the buffer to a different spatial reference and hold on to the geometry
- Use the reprojected buffer geometry to intersect a roads layer and get a road
- Use the road polyline geometry and find the distance along the road where the buffer first touches it
- Use the distance to "cut" the new polyline to produce a new polyline feature describing the affected road feature up to the point of intersection
- Return the polyline geometry and the distance along the polyline to the client for rendering
Getting your REST, and still getting something done
Consider the following diagram which should look familiar to those of you who attended Dave's talk Thursday morning last week. Let's take a closer look at what's going on.- In our example architecture, the user "map click" initiates a call to a RESTful URL (e.g., http://mywebsite/roadPoints/create http://mywebsite/roadPoints/get or http://mywebsite/lineclipper, etc.) on the web server
- IIS hands off our X,Y coordinate to ASP.NET MVC. The Routing engine in turn directs the request to the Create GET method on the RoadPoints controller. By the way, an MVC controller method is just a convenient and cogent example; any RESTful service endpoint REST resource will do (WCF, etc.). The point is to make this first hop look RESTful to a client application.
- Our MVC Controller uses SOAP to call a traditional WS-* web service on the ArcGIS Server box.
- The web service on the ArcGIS Server box uses an ADF connection to access a COM Utility or SOE running inside a SOC process
- Our custom COM utility or SOE does all of the buffering, reprojecting, intersecting, etc. (all the GIS "stuff" we're hiding from the user) using ArcObjects
- The result is returned to the web server, converted to JSON by the controller class, and is sent back over the wire as JSON for rendering in the client.
What it gets you
In short, we've abridged the six step GIS process described near the beginning of this post to: "Here's a point, hand me a road segment and a mile marker." We've transferred what would have been client workload into an MVC controller class and a web service on the server side, reducing chatter on the wire, increasing performance. We've left the GIS in the hands of custom ArcObjects code (read: fast). In addition, we've done two other important things:- Encapsulated business logic where it belongs
- Increased testability of our application by keeping complex functionality out of the client