Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I'm adding a Dynamic Map Service to an ArcGIS Server JavaScript API map, and I need to get hold of each component layer and its fields, so I can run a query.

See the sample ArcGIS Server services directory at http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/HomelandSecurity/operations/MapServer

If you open this URL in a browser you can see the list of available layers (0,1,2) and each layer's fields.

How can I retrieve the list of fields programatically, within a JavaScript function? The code snippet below shows how to retrieve the layer endpoints, but I can't see how to get to the fields.

(One option is to add the layers as Feature Layers, but I'd prefer to avoid this if possible).

var url = "http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/HomelandSecurity/operations/MapServer/";
var dynLayer = new esri.layers.ArcGISDynamicMapServiceLayer(url);
map.addLayer(dynLayer);

dojo.connect(dynLayer, "onLoad", function() {
   var infos = dynLayer.layerInfos;
   for (var i = 0; i <= infos.length - 1; i++) {
       var layerId = infos[i].id;
       var restEndPoint = url + layerId;
       //restEndPoint is the layer's URL - how can I retrieve its fields?
   }
});

Thanks, Steve (cross-posted to the ArcGIS Server forum)

share|improve this question
add comment

2 Answers

up vote 4 down vote accepted

Use esri.request() to hit each layer's REST endpoint to get info about fields. Here's a simple example:

<html>
  <head>
    <script type="text/javascript">var djConfig = {parseOnLoad: true};</script>
    <script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.4"></script>
    <script type="text/javascript">
      dojo.require("esri.map");
      // var service_url = 'http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Hurricanes/NOAA_Tracks_1851_2007/MapServer/layers';
      var service_url = 'http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Fire/Sheep/MapServer/layers';

      function init() {
        esri.request({
          url: service_url,
          content: { f: 'json' },
          callbackParamName: 'callback',
          load: processServiceInfo,
          error: errorHandler
        });
      }
      // Runs once
      function processServiceInfo(info) {
        console.log('svc info: ', info);
        dojo.byId('info').innerHTML = '';
        dojo.forEach(info.layers, function(lyr) {

          // Add a new div for each Layer
          var lyr_div = dojo.create('div', { 
            id: 'layer_' + lyr.id,
            innerHTML: '<strong>Layer: ' + lyr.name + '</strong><br />'
          }, dojo.byId('info'));

          dojo.forEach(lyr.fields, function(field) {
            lyr_div.innerHTML += 'Name: ' + field.name + '; Alias: ' + field.alias + '<br />';
          });
        });
      }

      function errorHandler(err) {
        console.log('error: ', err);
      }

      dojo.ready(init);
    </script>
  </head>
  <body>
    <div id="info">field names and aliases will show up here.</div>
  </body>
</html>

That code uses v2.0 of the API but the same thing will work at 2.3 or 2.4. I originally posted in the Esri JS API forum.

Edit: Updated to handle all layers in a service. The code also now uses version 2.4 of the API.

share|improve this answer
    
+1 Looks good. Since user has 3 layers though, maybe having init call a FieldsInit function for each layer might be more useful. –  Kirk Kuykendall Aug 16 '11 at 14:20
    
esri.request is the way to go, but instead of querying individual layers, just query them all at once by using http://..../MapServer/layers?f=json as the URL. –  Sasa Ivetic Aug 16 '11 at 14:54
    
Between you all, I think we have a great answer :) @Derek can you edit the code to handle all layers as per Sasa's suggestion, and I'll mark it as accepted? Thanks everyone –  Stephen Lead Aug 16 '11 at 21:01
    
There ya go Steve...updated my code sample to provide info for all layers in a map service. –  Derek Swingley Aug 16 '11 at 22:55
    
Thanks. I'm loading the JSON result into a global variable which I can then access at any time, to determine the layers and fields available in the map. Brilliant. –  Stephen Lead Aug 17 '11 at 1:19
add comment

I may have the wrong end of the stick here, but don't you just perform a query on the layer in question and get the results back as a resultset? If you ask for it in json, you can parse the results?

So for this:

http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer/1/query?where=STATE_NAME%3D%27Florida%27&f=json

The return is:

{"displayFieldName":"STATE_NAME","fieldAliases":{"STATE_NAME":"STATE_NAME"},"geometryType":"esriGeometryPolygon","spatialReference":{"wkid":4326},"fields":[{"name":"STATE_NAME","type":"esriFieldTypeString","alias":"STATE_NAME","length":25}],"features":[{"attributes":{"STATE_NAME":"Florida"},"geometry":{"rings":[[[-80.785662408630856,28.785194039580265], ... [-80.5878197219821,24.956376399079556],[-80.249453677873134,25.354937642313288]]]}}]}

(I have removed most of the geometry to make it easier reading)

share|improve this answer
    
how did you know to query layer 1, and that there was a field called STATE_NAME? That's what I'm trying to work out on-the-fly (ie, I need this to work for ANY rest endpoint at run-time, not one that I know beforehand). Thanks –  Stephen Lead Aug 16 '11 at 9:22
    
well the simplest answer would be to count the layers in the map service, and each other map service, and loop through them requesting the data. A query can just be a null one, so you bring everything back. You can then loop through the response listing the data. –  Hairy Aug 16 '11 at 9:41
    
so in my example above, I'd set a QueryTask based on each restEndPoint, and build a query which didn't return geometry - good idea. I'll give it a try - thanks! –  Stephen Lead Aug 16 '11 at 10:30
    
That's how I'd approach it –  Hairy Aug 16 '11 at 10:32
    
Try this: Url to layer URL/YOURLAYERNAME/MapServer/layers?f=json - This should return a json depiction of all your layers and their fields or URL/YOURLAYERNAME/MapServer/1?f=json indicating the layer number you want –  Hairy Aug 16 '11 at 10:45
show 3 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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