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
Sure this is just an example to make a point, but it makes it well. Our RESTful service calls look something like the following diagram.

Pretty chatty eh? Does the user care about the GIS involved…no. They want to click the map, have a portion of a road segment highlight, and they want to see a mile marker value. With so much going on in the client, business logic is bound to slip in: When the client get’s one of those individual responses back, how does the response get validated before continuing along the operation chain? How do you unit test it if it resides in the client? In addition, while RESTful architectures are definitely performant in the main, all this chatter on the wire suffers from latency; latency in transfer and latency in serialization/deserialization at the endpoints. And there is a better way.
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
But what about..?
Some of you may be thinking “Wait just a gall-dern minute! I see SOAP, WS-*, and ADF in that diagram.” Horse-pucky I say…the guts don’t matter. All that matters is how you surface the original request for the client. The client sees a REST endpoint resource, and get’s the answer the user wants quickly.
Conclusion
Much has been written in the ESRI realm about the power and utility of COM utilities and Server Object Extensions (SOEs). Don’t assume that the RESTful nature of your architecture needs to stop where the ESRI REST API or the ASP.NET MVC toolbox does. That’s the beauty of REST…bolting together high performance, URI-based services and application components that may or may not be of your own making. Surfacing custom server side components in this way provides an excellent means to providing focused, high performance applications with advanced capabilities not currently available in the ArcGIS Server SOAP and REST APIs. This approach encapsulates (hides) complexity from the user, is highly performant, and represents a simple reorganization of technologies most of us geo-geeks are already used to using.

Completely agree that it’s okay to use SOAP or WxS or other RPC behind the curtain, and this is a fine how-to. My only quibble is with your “REST endpoint” terminology. There aren’t any “endpoints” in web architecture, only “resources”. (BTW, I think you’ll enjoy reading http://www.w3.org/TR/webarch/.) When you use a term like “REST endpoint”, SOAP is leaking through into your vocabulary, your thinking, and perhaps unintentionally into your RESTful architecture.
While an abundance of POST-only resources that do stuff like clip features is probably unavoidable in RESTful GIS, we can try to make them the best resources they can be. A GET request to your clipper resource probably should return a form that enumerates all the different layers that it can clip. Likewise, representations of layers should provide links to the different geoprocessing resources that can act on them. This explains important business rules to clients on a need-to-know basis.
I was thrown for a moment by your clipper resource’s URI: http://…/roadPoints/create. Unless this thing is creating new state stored on the server side, “create” is misleading. If it’s just returning JSON data and “200 OK”, rename it to http://…/lineclipper or something.
Sean,
Good points on both the semantics and the example URI…REST is resources. I tend to play a little fast and loose with semantics of this stuff. I agree on the URI and should have swapped it out before posting this…this post came together over two different plane rides with lots of copy paste. We definintely are not “creating” anything on the server aside from the JSON that comes back to the client so the request is a GET and the URI contains an incorrect verb.
Brian
I wouldn’t sweat POST vs GET in this case. If the clipped road segment entity is disposable, if you’re never going to cache it or refer to it in any other context, POST is fine.
[...] http://www.surf.co.nz/reports/ AGS Article page_revision: 1, last_edited: 1244710829|%e %b %Y, %H:%M %Z (%O ago) edittags history files [...]