How to retrieve the Fields available in a Dynamic map's sub-layers

2163
10
08-15-2011 09:04 PM
StephenLead
Regular Contributor III
See the sample below, which adds a DynamicMapServiceLayer to a map using the URL:

http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/HomelandSecurity/operations/MapServer

Navigating to this REST endpoint in a browser shows the component Layers, and each layer's Fields.

How can I retrieve this information programatically? I need a list of the available layers (0,1,2) and each layer's available fields (eg layer 0 contains objectid, lifecyclestatus, incident_number, etc)

My goal is to add this information to a Query function, so I need to know that I can search layer 1 for the field collection_time, etc.

Looping through the layerInfos tells me about each available layer - how can I retrieve information on the fields? (One option is to create a new feature layer from each layer and add it to the map, but I'd really like to avoid this workaround).

Thanks,
Steve

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=7,IE=9" />
    <!--The viewport meta tag is used to improve the presentation and behavior of the samples 
      on iOS devices-->
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
    <title>layer infos</title>
    <link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/2.4/js/dojo/dijit/themes/claro/claro.css">
    <script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.4"></script>
    <script type="text/javascript">
      dojo.require("esri.map");

      function init() {
        var map = new esri.Map("map");
        
        var basemap = new esri.layers.ArcGISTiledMapServiceLayer("http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer");
        map.addLayer(basemap);

        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.id;
                var restEndPoint = url + layerId;

                //restEndPoint is the layer's URL - how can I retrieve its fields?

            }
        });
        
      }

      dojo.addOnLoad(init);
    </script>
  </head>
  <body class="claro">
    <div id="map" style="width:900px; height:600px; border:1px solid #000;"></div>
  </body>
</html>
0 Kudos
10 Replies
HemingZhu
Occasional Contributor III
See the sample below, which adds a DynamicMapServiceLayer to a map using the URL:

http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/HomelandSecurity/operations/MapServer

Navigating to this REST endpoint in a browser shows the component Layers, and each layer's Fields.

How can I retrieve this information programatically? I need a list of the available layers (0,1,2) and each layer's available fields (eg layer 0 contains objectid, lifecyclestatus, incident_number, etc)

My goal is to add this information to a Query function, so I need to know that I can search layer 1 for the field collection_time, etc.

Looping through the layerInfos tells me about each available layer - how can I retrieve information on the fields? (One option is to create a new feature layer from each layer and add it to the map, but I'd really like to avoid this workaround).

Thanks,
Steve

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=7,IE=9" />
    <!--The viewport meta tag is used to improve the presentation and behavior of the samples 
      on iOS devices-->
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
    <title>layer infos</title>
    <link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/2.4/js/dojo/dijit/themes/claro/claro.css">
    <script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.4"></script>
    <script type="text/javascript">
      dojo.require("esri.map");

      function init() {
        var map = new esri.Map("map");
        
        var basemap = new esri.layers.ArcGISTiledMapServiceLayer("http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer");
        map.addLayer(basemap);

        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.id;
                var restEndPoint = url + layerId;

                //restEndPoint is the layer's URL - how can I retrieve its fields?

            }
        });
        
      }

      dojo.addOnLoad(init);
    </script>
  </head>
  <body class="claro">
    <div id="map" style="width:900px; height:600px; border:1px solid #000;"></div>
  </body>
</html>


That is a good question. I thought this before when i was developing an app. Unfortunately i don't  think you could find a property or a method (other than featuelayer) to get field info without extra steps. One work around i thought about is putting field infos for each layer in .mxd description, and then getting them through layer.description. Of cause, you need put them in .mxd description in a way that you could manipulate them through string functions to get the field name out.
0 Kudos
StephenLead
Regular Contributor III
Storing the info in the MXD is a good workaround, but I need something guaranteed to work (ie, without the dependency on the MXD author to remember to make the change).

What about doing something with a JSON request, like in this sample? Do you think this would work?

The URL http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/HomelandSecurity/operations/MapServer/lay... returns a JSON string containing the field names, but I can't work out how to access this using the JSON request methodology in that sample. Can you give any clues?

Cheers,
Steve
0 Kudos
derekswingley1
Frequent Contributor
0 Kudos
HemingZhu
Occasional Contributor III
Storing the info in the MXD is a good workaround, but I need something guaranteed to work (ie, without the dependency on the MXD author to remember to make the change).

What about doing something with a JSON request, like in this sample? Do you think this would work?

The URL http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/HomelandSecurity/operations/MapServer/lay... returns a JSON string containing the field names, but I can't work out how to access this using the JSON request methodology in that sample. Can you give any clues?

Cheers,
Steve


Steve, Json request would definitely work. However these are extra steps (trips to server). Just image you have many layers! If you really want to use json request, more feasible way would be put your fields info into a txt or dat file, and use json request to get the file content and go from there.
0 Kudos
JohnGrayson
Esri Regular Contributor
If available, you could use the '/layers' REST endpoint to get back all the information you need in a single call.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=7,IE=9" />
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
    <title>Create Map</title>
    <link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/2.4/js/dojo/dijit/themes/claro/claro.css">
    <script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.4"></script>

    <script type="text/javascript">
      dojo.require("esri.map");
      function init() {
        var map = new esri.Map("map");
        var imageParameters = new esri.layers.ImageParameters();
        imageParameters.format = "jpeg";
        var dynamicMapServiceLayer = new esri.layers.ArcGISDynamicMapServiceLayer("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/HomelandSecurity/operations/MapServer", {
          "opacity":0.5,
          "imageParameters":imageParameters
        });
        map.addLayer(dynamicMapServiceLayer);
        // GET MAP SERVICE INFORMATION
        getMapServiceInformation(dynamicMapServiceLayer.url);
      }
      // GET MAP SERVICE INFORMATION      
      function getMapServiceInformation(mapServiceUrl) {
        var mapServiceInfoDeferred = esri.request({
          url: dojo.replace("{0}/layers",[mapServiceUrl]),
          content: {
            f: 'json'
          },
          callbackParamName: "callback"
        });
        mapServiceInfoDeferred.then( function(response) {
          // THE INFORMATION RETURNED HERE IS NOT THE SAME OBJECT/INSTANCE AS 
          // THE JS API LAYER CREATED ABOBE, IT'S JUST A SIMPLE JSON OBJECT
          // REPRESENTATION OF MAP SERVICE INFORMAITON
          dojo.forEach(response.layers, function(layerInfo) {
            var layerInfoNode = dojo.create('li', {
              'innerHTML': dojo.replace("<b>{name}</b> [{type}]",layerInfo),
              'style':'font-size:larger;margin-bottom:20px;'
            },'mapServiceInfo');
            if(layerInfo.fields) {
              var fieldsInfoNode = dojo.create('ul', {
              },layerInfoNode);
              dojo.forEach(layerInfo.fields, function(fieldInfo) {
                var fieldInfoNode = dojo.create('li', {
                  'innerHTML': dojo.replace("<b>{name}</b> (<i>{alias}</i>) {type}",fieldInfo)
                },fieldsInfoNode);
              });
            }
          });
        }, function(error) {
          dojo.byId('mapServiceInfo').innerHTML = dojo.toJson(error);
        });
      }
      dojo.addOnLoad(init);
    </script>
  </head>
  <body class="claro">
    <div id="map" style="width:500px; height:300px; border:1px solid #000;">
    </div>
    <ul id="mapServiceInfo">
    </ul>
  </body>
</html>
0 Kudos
HemingZhu
Occasional Contributor III
If available, you could use the '/layers' REST endpoint to get back all the information you need in a single call.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=7,IE=9" />
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
    <title>Create Map</title>
    <link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/2.4/js/dojo/dijit/themes/claro/claro.css">
    <script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.4"></script>

    <script type="text/javascript">
      dojo.require("esri.map");
      function init() {
        var map = new esri.Map("map");
        var imageParameters = new esri.layers.ImageParameters();
        imageParameters.format = "jpeg";
        var dynamicMapServiceLayer = new esri.layers.ArcGISDynamicMapServiceLayer("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/HomelandSecurity/operations/MapServer", {
          "opacity":0.5,
          "imageParameters":imageParameters
        });
        map.addLayer(dynamicMapServiceLayer);
        // GET MAP SERVICE INFORMATION
        getMapServiceInformation(dynamicMapServiceLayer.url);
      }
      // GET MAP SERVICE INFORMATION      
      function getMapServiceInformation(mapServiceUrl) {
        var mapServiceInfoDeferred = esri.request({
          url: dojo.replace("{0}/layers",[mapServiceUrl]),
          content: {
            f: 'json'
          },
          callbackParamName: "callback"
        });
        mapServiceInfoDeferred.then( function(response) {
          // THE INFORMATION RETURNED HERE IS NOT THE SAME OBJECT/INSTANCE AS 
          // THE JS API LAYER CREATED ABOBE, IT'S JUST A SIMPLE JSON OBJECT
          // REPRESENTATION OF MAP SERVICE INFORMAITON
          dojo.forEach(response.layers, function(layerInfo) {
            var layerInfoNode = dojo.create('li', {
              'innerHTML': dojo.replace("<b>{name}</b> [{type}]",layerInfo),
              'style':'font-size:larger;margin-bottom:20px;'
            },'mapServiceInfo');
            if(layerInfo.fields) {
              var fieldsInfoNode = dojo.create('ul', {
              },layerInfoNode);
              dojo.forEach(layerInfo.fields, function(fieldInfo) {
                var fieldInfoNode = dojo.create('li', {
                  'innerHTML': dojo.replace("<b>{name}</b> (<i>{alias}</i>) {type}",fieldInfo)
                },fieldsInfoNode);
              });
            }
          });
        }, function(error) {
          dojo.byId('mapServiceInfo').innerHTML = dojo.toJson(error);
        });
      }
      dojo.addOnLoad(init);
    </script>
  </head>
  <body class="claro">
    <div id="map" style="width:500px; height:300px; border:1px solid #000;">
    </div>
    <ul id="mapServiceInfo">
    </ul>
  </body>
</html>


Good job! Gary. I missed that (ArcGIS server REST API -All Layers and Tables).
0 Kudos
StephenLead
Regular Contributor III
If available, you could use the '/layers' REST endpoint to get back all the information you need in a single call.


Thanks as always, John.
0 Kudos
AdrianMarsden
Occasional Contributor III
If available


..any reason why this wouldn't be available - it doesn't seem to be on my map services - is it a setting somewhere I have missed?

Cheers

ACM
0 Kudos
JohnGrayson
Esri Regular Contributor
I believe the 'All Layers and Tables' REST resource (<mapServiceUrl>/layers) was added at ArcGIS Server 10.0 (could be 10.0 sp1, but not 100% sure).  That is why I started my previous response with 'If available'...
0 Kudos