Working with the GeoIQ Features API




Part 1: Handling the JSON

I set out to develop a custom layer class, derived from the ESRI API’s native GraphicsLayer class. The bulk of the work was just parsing out the JSON to create the geometries and attach the attributes. If you’ve worked with the GraphicsLayer class before, this is fairly straightforward. I really just wanted to create a derived class that would take the various parameters of the GeoIQ API and do the heavy lifting behind the scenes.

I have really come to like JSON.Net by James Newton-King for handling JSON in my .Net code. It is open-source (MIT License) and I’ve grown comfortable with its LINQ to JSON features. Working with the native GeoIQ JSON, the code to build a list of graphic objects is pretty straightforward:

[sourcecode language=”csharp”]
/// <summary>
/// Iterates array of JSON objects and builds ESRI Graphics
/// </summary>
/// <param name="featArray">Array of JSON strings parsed from the original
/// returned from GeoIQ</param>
/// <returns></returns>
private void UnrollFeaturesEvent(JArray featArray)
var jEnum = featArray.AsJEnumerable();
foreach (JToken token in jEnum)
string s = token.ToString();
JObject feat = JObject.Parse(s);
Graphic graphic = new Graphic();
foreach (JProperty prop in feat.Properties())
var name = prop.Name;
if (name.ToLower() == GEOM_TOKEN) //handle feature geometry
var geom = GeometryFromWKB.Parse((string)prop.Value); //get geometry from hex-encoded WKB
geom.SpatialReference = new SpatialReference() { WKID = 4326 }; //GeoIQ returns geometries in WGS84
if (_useMercator) //do we want to use web mercator?
//_wm is an instance of ESRI.ArcGIS.Client.Projection.WebMercator
geom = _wm.FromGeographic(geom);
graphic.Geometry = geom;
else //we’re dealing with an attribute
object val = prop.Value == null ? "" : prop.Value;
graphic.Attributes.Add(prop.Name, val);
if (this.AddGraphic != null)
catch { }
Listing 1: Unrolling JSON Features from GeoCommons

You’ll notice the call to GeometryFromWKB.Parse above. The GeoIQ JSON returns geometries as hex-encoded WKB. To handle this, I modified GeometryFromWKB class from SharpMap to return an ESRI Silverlight API geometry. Yes, this means I managed to fuse two of Morten’s creations together here in some small way. 🙂

Part 2: Calling the Features API

So now that we can handle the JSON coming back from GeoIQ, we need to request it. The GeoIQ Features API defines a number of parameters that can be submitted to refine the set of features that is returned. For this pass, I am only implementing lat, lon, radius, units, bbox, intersect and limit. I am also not handling the use of geometries other than points for buffering right now. I set up all of these parameters as dependency properties. That code is rather repetitive but here is an example of how I wrapped one of them:

[sourcecode language=”csharp”]
// Using a DependencyProperty as the backing store for Limit.
public static readonly DependencyProperty LimitProperty =
DependencyProperty.Register("Limit", typeof(int), typeof(GeoCommonsGraphicsLayer), new PropertyMetadata(0));

public int Limit
get { return (int)GetValue(LimitProperty); }
set { SetValue(LimitProperty, value); }
Listing 2: Dependency property wrapping the “limit” parameter

The URI format for calling the Features API is describe in the GeoIQ documentation. From that document here is one example:

From here, it’s just a matter of building a valid URI to call using the WebClient (or HttpWebRequest if you prefer) so I start with a template string something like this:{0}/features.json?, where “{0}” is a placeholder for the GeoCommons overlay ID. I then build out the query string parameters by rolling up any properties that have been set. Note: for query parameters that have a fixed set of values, I used enumerations that I extend with attributes using the technique described at so that I could get the valid parameter values while presenting more human-readable enumerations. This probably isn’t necessary, but I’ve grown fond of the approach. Here’s an example:

[sourcecode language=”csharp”]
public enum UnitsValues
Kilometers = 1,
Meters = 2,
Feet = 3,
Miles = 4,
Degrees = 5
Listing 3: Example of enumeration using StringValue attributes

Once we make the call, we handle the reponse like so:

[sourcecode language=”csharp”]
void request_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
if (e.Error == null)
string json = e.Result;
var jsonHelper = new Zekiah.Helpers.GeoIqJson();
jsonHelper.AddGraphic += new AddGraphicHandler(jsonHelper_AddGraphic);
jsonHelper.GetFeatureGraphicsEvent(json, this.UseWebMercator);

void jsonHelper_AddGraphic(Graphic graphic)
this.Graphics.Add(graphic); //’this’ is the current instance of GeoCommonsGraphicsLayer
Listing 4: Populating the layer with the ESRI graphic objects

The code back up in Listing 1 fires an event every time a graphic is created. This saved me at least one iteration through the list of graphics and sped up loading somewhat. It was most noticeable on large GeoCommons overlays.

Part 3: Using the Custom Layer Class.

Once all this is wired up, we can access GeoCommons data from in two ways:

From XAML:

[sourcecode language=”xml”]
<esri:Map x:Name="Map" Background="White">
<esri:ArcGISTiledMapServiceLayer ID="BaseLayer"
Url="" />
<ztLayers:GeoCommonsGraphicsLayer ID="Pipelines" ProxyUrl="../ProxyHandler.ashx?" Limit="0" Radius="100" Units="Kilometers" OverlayID="68949" UseWebMercator="True" Visible="True" >
<esri:SimpleLineSymbol Color="Black" Width="1" Style="Solid" />
<esri:MapPoint X="-92.1" Y="34.5">
<esri:SpatialReference WKID="4326" />
Listing 5: Adding a GeoCommons layer in XAML

Or in code:

[sourcecode language=”csharp”]
GeoCommonsGraphicsLayer polygonLayer = new GeoCommonsGraphicsLayer();
polygonLayer.Renderer = new SimpleRenderer() { Symbol = GetPolygonSymbol() };
polygonLayer.ProxyUrl = "../ProxyHandler.ashx?";
polygonLayer.OverlayID = 68967;
polygonLayer.UseWebMercator = true; //I may refactor this to check the map’s SRID
Listing 6: Adding a GeoCommons layer in code

These two examples access data provided to GeoCommons by the State of Arkansas as described by Learon Dalby here. In XAML, we are accessing the railroad lines that intersect a 100KM buffer around the supplied point. In the second, we are loading all of the state senate district boundaries.

That’s fairly high-level overview of the integration tasks that were needed to provide access to GeoCommons from the ESRI Silverlight API using the GeoIQ Features API. I’ll post a sample project and code soon once I get things cleaned up a bit more. Stayed tuned…