This walk-through shows how to use a geoprocessing service from ArcGIS Server. Geoprocessing enables analysis of spatial and non-spatial data to obtain useful new information. Geoprocessing includes many analytical functions, such as buffer, layer overlay, data conversion and raster data operations. ArcGIS Server supports running models with multiple geoprocessing steps for sophisticated analysis. For general information about geoprocessing, see the ArcGIS desktop help topic on geoprocessing.

A geoprocessing service must have been created in order to use it with the ArcGIS JavaScript Extension for Virtual Earth. If your organization has an installation of ArcGIS Server, you can create and use geoprocessing services. For information on creating geoprocessing services, see the ArcGIS Server Help page on Geoprocessing services. If you know the URL of an ArcGIS Server machine with services you wish to use, you can use the Services Directory to obtain information about the geoprocessing service.

This walk-through parallels the live sample "Adding Geoprocessing results on the map" in the Interactive SDK, with some changes to illustrate functionality in the API. As usual, the complete code appears at the end of the walk-through.

Using a geoprocessing service to find drive-time polygons

This walk-through demonstrates how to use a geoprocessing service. The geoprocessing service in this example generates a polygon that shows the area that a driver may reach within a given time period from a specified point. The service can actually generate multiple drive-time polygons in a single request. In this example, we have hard-coded the drive times of 1, 2 and 3 minutes from a pre-selected location. In a real application, you would probably obtain the starting point from geocoding an address, a database lookup, or a user's click on the map. You could also allow the user to enter the desired driving times.

  1. Create a web page with a basic Virtual Earth map. You may use the walk-through in this Help, Creating a base map with Virtual Earth. Update the <title> of the page as desired. Save the file, for example to ArcGISVEGeoprocessing1.htm.
  2. Add a reference to the ArcGIS JavaScript client script. This is required for every page that uses the ArcGIS JavaScript Extension for Virtual Earth. Add this in the header section, just below the reference to the Virtual Earth script.
    CopyArcGIS JavaScript Extension for Virtual Earth script reference
    <script src="http://serverapi.arcgisonline.com/jsapi/ve/?v=1.4" type="text/javascript"></script>
  3. Modify the OnPageLoad method to center the map on San Francisco. We'll be generating the drive-time polygons here. Also set the map style to a road map, and hide the VE dashboard. Your OnPageLoad function should resemble:
    CopyModified map startup
    function OnPageLoad() {
        var centerat = new VELatLong(37.775, -122.4865);
        map = new VEMap('mymap');
        map.LoadMap(centerat,13,VEMapStyle.Road);
        map.HideDashboard();
    }
  4. Inside the <form> element of the body, add a button that the user will click to perform the geoprocessing. We will add the code to handle the click next. Also add an empty div to display messages during the geoprocessing request.
    CopyButton to execute geoprocessing
    Click to display drive time areas of 1, 2, and 3 minutes:
    <input type="button" id="runGPtask" value="Go" style="width:50px;" onclick="ExecuteTask()" />
    <div id="job"></div>
  5. In the script block, just after the close of the existing OnPageLoad function, add the ExecuteTask function. We will create this function in several steps to make it easier to understand. In the function, first delete any previously added shapes (in case the user ran the task previously). Then create the Geoprocessor task that we will execute, and set its URL for the service. Remember that you can get information about a service from the Services Directory.
    CopyExecuting the task: creating the Geoprocessor
    function ExecuteTask() {
        map.DeleteAllShapes();
        var task = new  ESRI.ArcGIS.VE.Geoprocessor();
        task.Url = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Network/ESRI_DriveTime_US/GPServer/CreateDriveTimePolygons";
        // more to come in next step...
    }
  6. Next in ExecuteTask, set up the inputs for the geoprocessing task. The input parameters must be an array of type ParameterValue. Declare a new JavaScript Array named parameters to hold the inputs. We need two parameters for our inputs: the starting location and the driving times. Declare the starting location parameter (startLocationParam). Set its three required properties: ParamName, DataType and Value. The ParamName and DataType must be taken from the service properties--you don't make up your own values here. Use the Services Directory if necessary to obtain this information. The Value property in this case holds the input features and their geometry in JSON format. JSON creates objects using name/value pairs separated by commas and surrounded by curly braces. The set of input features (infeatures) is an array, constructed with square brackets in the value of the name/value pair. See the code snippet below for a guide.

    The second input parameter specifies the drive times we want to use. As before, use the ParamName and DataType values from the ArcGIS Server service. The Value in this case is a space-separated list of the drive times in minutes. Add both of the ParameterValue objects to the parameters array--the example below uses the push() method that adds items to a JavaScript array.
    CopyExecuting the task: creating the parameters
    function ExecuteTask() {
        map.DeleteAllShapes();
        var task = new  ESRI.ArcGIS.VE.Geoprocessor();
        task.Url = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Network/ESRI_DriveTime_US/GPServer/CreateDriveTimePolygons";
    
        var parameters = new Array();
        var startLocationParam = new ESRI.ArcGIS.VE.ParameterValue();
        startLocationParam.ParamName = "Input_Location";
        startLocationParam.DataType = "GPFeatureRecordSetLayer";
        var geom = {x:-122.4865,y:37.775};
        var feature = {geometry : geom};
        var infeatures = {features : [feature]};
        startLocationParam.Value = infeatures;
    
        var driveTimeParam = new ESRI.ArcGIS.VE.ParameterValue();
        driveTimeParam.ParamName = "Drive_Times";
        driveTimeParam.DataType = "GPString";
        driveTimeParam.Value = "1 2 3";
    
        parameters.push(startLocationParam);
        parameters.push(driveTimeParam);
        // more to come in next step...
    }
  7. To complete the ExecuteTask function, execute the geoprocessing task using the parameters we've set up. As usual when executing tasks, the second argument is the name of the function that will receive the results. We'll add this function next. At the end of the ExecuteTask function, display a message that indicates the task is processing. You can use the $get function built into ASP.NET AJAX, which is a shortcut for the document.getElementById function. The code snippet below shows the complete ExecuteTask function, including the code from the two previous steps.
    CopyExecuting the task: complete function
    function ExecuteTask() {
        map.DeleteAllShapes();
        var task = new  ESRI.ArcGIS.VE.Geoprocessor();
        task.Url = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Network/ESRI_DriveTime_US/GPServer/CreateDriveTimePolygons";
    
        var parameters = new Array();
        var startLocationParam = new ESRI.ArcGIS.VE.ParameterValue();
        startLocationParam.ParamName = "Input_Location";
        startLocationParam.DataType = "GPFeatureRecordSetLayer";
        var geom = {x:-122.4865,y:37.775};
        var feature = {geometry : geom};
        var infeatures = {features : [feature]};
        startLocationParam.Value = infeatures;
    
        var driveTimeParam = new ESRI.ArcGIS.VE.ParameterValue();
        driveTimeParam.ParamName = "Drive_Times";
        driveTimeParam.DataType = "GPString";
        driveTimeParam.Value = "1 2 3";
    
        parameters.push(startLocationParam);
        parameters.push(driveTimeParam);
    
        task.Execute(parameters, showResults);
        var div = $get("job");
        div.innerHTML = "Executing. . .";
        div.style.cursor = "wait";
    }
  8. Add the showResults function that will receive the results of the geoprocessing task. We will also break up the discussion of this function into a couple of steps to clarify what is happening. The function takes the results of the geoprocessing task as its argument. The results (gpResult) are an instance of the GPResults class. To start the function, check for any errors and display them if found.

    If no errors occur, then display the drive-time polygons from the results on the map. Do this by, first, constructing a new VEShapeLayer to hold the polygons. We could have added the shapes directly to the map, but the VEShapeLayer allows you to control the display of the entire group of shapes. Next, loop through the gpResult's Results, which is an array of ParameterValue objects. In this case, only one ParameterValue will be returned--other geoprocessing services may return multiple items. So far our showResults function looks like this: 
    CopyFunction handling geoprocessing results - part 1
    function showResults(gpResult) {
        var err = gpResult.Error;
        if (err!=null) 
            alert(err.message);
        else {
            var layer = new VEShapeLayer(); 
            var results = gpResult.Results;
            if (results.length>0) {
                for (var d=0;d<results.length;d++) {
    
                    // we'll add the rest of the code in next step
    
                }
            }
        }
    }
  9. To complete the display of the returned features, get the Value of each ParameterValue, which is a FeatureSet object. Get the Features from the FeatureSet, which is an array of GraphicFeature objects. Each GraphicFeature has the drive-time polygon representing the travel area for one of the travel times we submitted (1, 2 or 3 minutes). Loop through these features and get the Shapes of each. These are an array of VEShape objects.  We can add these shapes to the VEShapeLayer created earlier.

    Before adding the shapes, set the color for the set of shapes so that we distinguish between the polygon for each travel time. The VEColor includes partial transparency (4th argument, 0.5) so the user can view the map underneath. Then loop through the shapes (actually there is probably only one polygon), set the color and other display properties, and add the shape to the VEShapeLayer.

    Finally, after close of the loop for the results, add the shape layer to the map and set it to display. Before the close of the function, display a message to the user that the geoprocessing task has completed.

    CopyFunction handling geoprocessing results - complete
    function showResults(gpResult) {
        var err = gpResult.Error;
        if (err!=null) 
            alert(err.message);
        else {
            var layer = new VEShapeLayer(); 
            var results = gpResult.Results;
            if (results.length>0) {
                for (var d=0;d<results.length;d++) {
                    var featureSet = results[d].Value;
                    var features = featureSet.Features;
                    for (var f=0;f<features.length;f++) {
                        var shapes = features[f].Shapes;
                        if(f == 0) {
                              color = new VEColor(255,153,153,0.5);
                        } else if(f== 1) {
                              color = new VEColor(255,255,153,0.5);
                        } else if(f== 2) {
                              color = new VEColor(153,153,255,0.5);
                        }
                        var lineColor = new VEColor(0,0,0,0.5);
                        for (var ss=0;ss<shapes.length;ss++) {
                            var shape = shapes[ss];
                            shape.SetLineColor(lineColor);
                            shape.SetFillColor(color);
                            shape.SetLineWidth(2);
                            shape.HideIcon();
                            shape.Show();
                            layer.AddShape(shape);
                        }
                    }
                }
            }
            map.AddShapeLayer(layer);
            layer.Show();
        }
        var div = $get("job");
        div.innerHTML = "Completed.";
        div.style.cursor = "default";
    }
  10. Save the page, and open it in a browser. It should load the VE map, with the button to run the geoprocessing task below. Click the button to initiate the task. A message should display indicating the task has begun execution. After a few moments, the three drive-time polygons should display in distinguising colors surrounding the starting point. Note that the starting point itself does not display--you might make that a challenge step for this walk-through.

Discussion

Geoprocessing tasks may also be processed asynchronously. When a task is executed asynchronously, the job is submitted, then other operations may be performed while the job is completed, rather than waiting, as with the service used in this walk-through. The administrator of the ArcGIS Server machine determines whether a particular task runs synchronously or asynchronously. The Services Directory will tell you which execution method is used, in the properties of the geoprocessing service.

When a task executes asynchronously, you use the SubmitJob method on the Geoprocessor rather than the Execute method. SubmitJob requires a parameter with the name of the function that will handle the results, similar to the approach used for Execute. However, SubmitJob also has an optional third parameter, which is a the name of a function that will receive a report on the status of the task. This function can then report progress on the task to the user, perhaps by updating a div label with the status. See the sample "Monitoring Geoprocessing job status" in the Interactive SDK for an example. You can also cancel the execution of the task if it runs too long. See the sample "Cancel a submitted Geoprocessing job" in the Interactive SDK.

Complete code for this walkthrough

CopyExample: Working with a geoprocessing service
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>Working with a geoprocessing service</title>
    <script src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2" type="text/javascript"></script>
    <script src="http://serverapi.arcgisonline.com/jsapi/ve/?v=1.4" type="text/javascript"></script>
    <script language="javascript" type="text/javascript" >
        var map = null;

        function OnPageLoad() {
            var centerat = new VELatLong(37.775, -122.4865);
            map = new VEMap('mymap');
            map.LoadMap(centerat,13,VEMapStyle.Road);
            map.HideDashboard();
        }

        function ExecuteTask() {
            map.DeleteAllShapes();
            var task = new  ESRI.ArcGIS.VE.Geoprocessor();
            task.Url = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Network/ESRI_DriveTime_US/GPServer/CreateDriveTimePolygons";

            var parameters = new Array();
            var startLocationParam = new ESRI.ArcGIS.VE.ParameterValue();
            startLocationParam.ParamName = "Input_Location";
            startLocationParam.DataType = "GPFeatureRecordSetLayer";
            var geom = {x:-122.4865,y:37.775};
            var feature = {geometry : geom};
            var infeatures = {features : [feature]};
            startLocationParam.Value = infeatures;

            var driveTimeParam = new ESRI.ArcGIS.VE.ParameterValue();
            driveTimeParam.ParamName = "Drive_Times";
            driveTimeParam.DataType = "GPString";
            driveTimeParam.Value = "1 2 3";

            parameters.push(startLocationParam);
            parameters.push(driveTimeParam);

            task.Execute(parameters, showResults);
            var div = $get("job");
            div.innerHTML = "Executing. . .";
            div.style.cursor = "wait";
        }

        function showResults(gpResult) {
            var err = gpResult.Error;
            if (err!=null) 
                alert(err.message);
            else {
                var layer = new VEShapeLayer(); 
                var results = gpResult.Results;
                if (results.length>0) {
                    for (var d=0;d<results.length;d++) {
                        var featureSet = results[d].Value;
                        var features = featureSet.Features;
                        for (var f=0;f<features.length;f++) {
                            var shapes = features[f].Shapes;
                            if(f == 0) {
                                  color = new VEColor(255,153,153,0.5);
                            } else if(f== 1) {
                                  color = new VEColor(255,255,153,0.5);
                            } else if(f== 2) {
                                  color = new VEColor(153,153,255,0.5);
                            }
                            var lineColor = new VEColor(0,0,0,0.5);
                            for (var ss=0;ss<shapes.length;ss++) {
                                var shape = shapes[ss];
                                shape.SetLineColor(lineColor);
                                shape.SetFillColor(color);
                                shape.SetLineWidth(2);
                                shape.HideIcon();
                                shape.Show();
                                layer.AddShape(shape);
                            }
                        }
                    }
                }
                map.AddShapeLayer(layer);
                layer.Show();
            }
            var div = $get("job");
            div.innerHTML = "Completed.";
            div.style.cursor = "default";
        }

    </script>
</head>
<body onload="OnPageLoad()" >
    <form action="" >
    <div id='mymap' style="position:relative; width: 750px; height: 500px;"></div>
    Click to display drive time areas of 1, 2, and 3 minutes:
    <input type="button" id="runGPtask" value="Go" style="width:50px;" onclick="ExecuteTask()" />
    <div id="job"></div>
    </form>
</body>
</html>