0

I have a Leaflet map in which I am displaying an Esri ArcGIS REST layer, using L.esri.dynamicMapLayer(). The code that initializes this layer is passed the URL to the service and a comma-separated list of layers to be displayed - which service and which layers is configured by the user.

My task is to provide a means by which the user can click on the map and obtain feature information for the nearby facilities. I had been looking at L.esri.query(), which was simply inappropriate.

Looking at L.esri.DynamicMapLayer, I see that it has a function identify(), which should return an IdentifyFeatures object. But I'm not having any luck with using it. Everything I try results in a

bbox must be specified

error.

The documentation for dynamicMapLayer is here: dynamic-map-layer.html It includes:

Returns a new L.esri.services.IdentifyFeatures object that can be used to identify features on this layer. Your callback function will be passed a GeoJSON FeatureCollection with the results or an error.

dynamicMapLayer.identify()
  .at(latlng, latlngbounds, 5)
  .run(function(error, featureCollection){
     console.log(featureCollection);
});

Note that .at() is called with a latlong object, a latlngbounds object, and "5".

But the documentation for the IdentifyFeatures object is here: identify-features.html

And it's documentation for at() is:

at( latlng) this Identifies feautres at a given

Only one argument. No second bounds argument, or third numeric argument, simply a LatLng. The LatLng links to the Leaflet code, indicating that it's an L.latLng object, containing a lat and a lng property.

The example code for IdentifyFeatures is even more confusing:

L.esri.identifyFeatures({
  url: 'http://sampleserver6.arcgisonline.com/arcgis/rest/services/WorldTimeZones/MapServer'
})
.on(map)
.at([45.543, -122.621])
.layers('visible:1')
.run(function(error, featureCollection, response){
    console.log("UTC Offset: " + featureCollection.features[0].properties.ZONE);
});

Here, we're not passing a L.latLng object, we're passing an array.

What gives? How am I supposed to use this?


After some clarification as to what the proper arguments should be, I passed a single LatLng object, and continued to get the "bbox must be specified" error.

Tracking this down into the JS libraries, I discovered that this error message is being returned by the server. The esri-leaflet is building up the URL below, sending it to our customer's ArcGIS REST server, and getting back the error.

https://gis.elided.invalid/arcgis/rest/services/Secure/Korweb_App/MapServer/export/identify?sr=4326&layers=all&tolerance=3&returnGeometry=true&imageDisplay=431%2C600%2C96&mapExtent=-75.59185445308685%2C40.99650425834298%2C-75.58954238891602%2C40.998933489018704&geometry=-75.59079766273499%2C40.998492185433854&geometryType=esriGeometryPoint&f=json

I'm eliding the actual URL because one, this is a customer's production site, and I haven't permission to allow anyone else to access, and because it's behind an IP-filtering firewall, and nobody could access it, anyway.

So, we're down to the real question - should this URL have worked? Is there a bbox argument that should have been passed, that was somehow left out? Or is this a correct URL, and there's something on the server that has been misconfigured?


OK, it was something stupid.

Esri's ArcGIS REST API uses a base URL that looks like this:

https://tmservices1.esri.com/arcgis/rest/services/LiveFeeds/Earthquakes/MapServer

To which it appends the various actions that are requested. To export an image, you call:

https://tmservices1.esri.com/arcgis/rest/services/LiveFeeds/Earthquakes/MapServer/export/????

To do an identify, you call:

https://tmservices1.esri.com/arcgis/rest/services/LiveFeeds/Earthquakes/MapServer/identify/????

The configuration we were building our map from was handed a URL that ended in "/export". As a result, when we did an identify, we called a URL that included "/export/identify", so we weren't asking for an identify, we were asking for an export, and were passing invalid arguments.

1
  • thanks for taking the time to loop back and explain the fix. Mar 7, 2016 at 22:25

1 Answer 1

1
  1. the L.esri.dynamicMapLayer code snippet is incorrect. at() expects an L.latLng object to be passed as the sole argument. thanks for pointing out the issue. i've corrected the problem and will push the fix to the live site soon.
  2. the identifyFeatures code snippet and live sample both provide valid examples of how to work with the task.
  3. its a leaflet convention that a cast L.latLng object and a raw [lat,lng] array can be used interchangeably.

http://leafletjs.com/reference.html#latlng

All Leaflet methods that accept LatLng objects also accept them in a simple Array form and simple object form (unless noted otherwise)

5
  • So why, when I pass a LatLng object, do I get a "bbox must be specified" error.
    – Jeff Dege
    Mar 5, 2016 at 12:37
  • i don't see the same problem in our live sample, so you'll have to show me some code of your own (preferably in a jsbin or fiddle) if you need some help debugging. Mar 7, 2016 at 17:17
  • Can't do a jsbin or fiddle because we're hitting a arcgis server that you'd not have access to. I've posted the actual hhtp request, above.
    – Jeff Dege
    Mar 7, 2016 at 18:02
  • do you see the same problem when you swap in a public sample service url in your own code? if so, a fiddle pointing at the new service would work just fine. Mar 7, 2016 at 18:08
  • Haven't, yet. That's the next thing to try, once I get out of the damned meetings I'm being dragged into.
    – Jeff Dege
    Mar 7, 2016 at 20:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.