ArcGIS Buffer geoprocessing
ArcGIS_Buffer_Geoprocessing_CSharp\Default.aspx.cs
// Copyright 2010 ESRI
// 
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
// 
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
// 
// See the use restrictions.
// 

public partial class _Default : System.Web.UI.Page
{
    #region Instance Variable Declarations

  // Name of the geoproccessing resource containing the BufferPoints task
    private string _geoprocessingResourceName = "Buffer Resource";

    // Name of the resource in which to store geoprocessing results
    private string _graphicsResourceName = "Web ADF Graphics";

    // Name of the graphics layers that will hold result buffers and user-placed points
    private string _bufferGraphicsLayerName = "Buffer";
    private string _pointGraphicsLayerName = "Points";

    private ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResultCollection 
    _callbackResultCollection = new ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResultCollection();

    #endregion

    #region ASP.NET Page Life Cycle Event Handlers

    protected void Page_PreRender(object sender, System.EventArgs eventArgs)
    {
        try
        {
            // Initialize session variables only if the page request is occurring at the beginning of a session
            if (Page.Session.IsNewSession)
            {
                Session["graphicsResourceName"] = _graphicsResourceName;
                Session["pointGraphicsLayerName"] = _pointGraphicsLayerName;
            }

            // Make sure control initialization only occurs during initial page load or on page refresh
            if (!ScriptManager1.IsInAsyncPostBack)
            {
                // Add all the ArcGIS Server unit types to the units drop-down list except for unknown, points, 
                // and decimal degress
                System.Array agsUnitTypes = System.Enum.GetValues(typeof(ESRI.ArcGIS.ADF.Web.DataSources.Units));
                foreach (int agsUnitType in agsUnitTypes)
                {
                    string unit = agsUnitTypes.GetValue(agsUnitType).ToString();
                    if ((unit != "Unknown") && (unit != "DecimalDegrees") && (unit != "Points"))
                        UnitsDropDownList.Items.Add(unit);
                }
            }
        }
        catch (System.Exception exception)
        {
            string jsErrorAlertString = string.Format("<script>{0}</script>",
                Utility.GetJavaScriptErrorString(exception));
            Response.Write(jsErrorAlertString);
        }
    }

    protected void Page_Load(object sender, System.EventArgs eventArgs)
    {
    // Register the buttons so they initiate asynchronous postbacks 
    ScriptManager1.RegisterAsyncPostBackControl(BufferButton);
    ScriptManager1.RegisterAsyncPostBackControl(ClearGraphicsButton);

    BufferButton.Click += new System.EventHandler(BufferButton_Click);
    ClearGraphicsButton.Click += new System.EventHandler(ClearGraphicsButton_Click);

    PostbackManager1.RequestReceived += 
      new PostbackManager_CSharp.RequestReceivedEventHandler(PostbackManager1_RequestReceived);
  }

    #endregion

  #region Request Handling

  void PostbackManager1_RequestReceived(object sender, PostbackManager_CSharp.AdfRequestEventArgs args)
  {
    // Use the Web ADF's callback utility to parse the arguments into a NameValueCollection
    System.Collections.Specialized.NameValueCollection requestArgs =
      ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(args.RequestArguments);

    if (requestArgs["EventArg"] == "CheckJobStatus")
    {
      try
      {
        // Call the method to heck whether the geoprocssing job is finished and process results if so
        CheckJobStatus(requestArgs["JobID"], requestArgs["TaskName"], requestArgs["OutputParameters"]);
      }
      catch (System.Exception exception)
      {
        ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult errorCallbackResult =
          Utility.CreateErrorCallbackResult(exception);
        _callbackResultCollection.Add(errorCallbackResult);
      }
      finally
      {
        PostbackManager1.CallbackResults.CopyFrom(_callbackResultCollection);
      }
    }
  }

  #endregion

  #region ASP.NET Web Control Event Handlers

  public void BufferButton_Click(object sender, System.EventArgs e)
  {
    try
    {
      // Get the buffer operation parameters specified by the user
      string bufferDistanceString = BufferDistanceTextBox.Text;
      double bufferDistance = 0;
      double.TryParse(bufferDistanceString, out bufferDistance);

      // Invoke the method to initiate the geoprocessing task
      StartBufferJob(bufferDistance, UnitsDropDownList.SelectedValue);
    }
    catch (System.Exception exception)
    {
      ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult errorCallbackResult =
        Utility.CreateErrorCallbackResult(exception);
      _callbackResultCollection.Add(errorCallbackResult);
    }
    finally 
    {
      ScriptManager1.RegisterDataItem(Page, _callbackResultCollection.ToString(), false);
    }
  }

  public void ClearGraphicsButton_Click(object sender, System.EventArgs e)
  {
    try
    {
      // Invoke the method to clear the graphics from the map
      ClearGraphics();
    }
    catch (System.Exception exception)
    {
      ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult errorCallbackResult =
        Utility.CreateErrorCallbackResult(exception);
      _callbackResultCollection.Add(errorCallbackResult);
    }
    finally
    {
      ScriptManager1.RegisterDataItem(Page, _callbackResultCollection.ToString(), false);
    }
  }

    #endregion

    #region Instance Methods

    // Initiates the buffer points geoprocessing job with the passed-in parameters
    private void StartBufferJob(double bufferDistance, string units)
    {
        #region Initialize resources and functionalities

        // Initialize GP resource and functionality
        ESRI.ArcGIS.ADF.Web.UI.WebControls.GeoprocessingResourceItem geoprocessingResourceItem =
            GeoprocessingResourceManager1.ResourceItems.Find(_geoprocessingResourceName);

        // Make sure the geoprocessing resource is initialized
        if (!geoprocessingResourceItem.Resource.Initialized)
            geoprocessingResourceItem.InitializeResource();

        // Get a reference to the GP resource and its functionality
        ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingResource geoprocessingResource =
            (ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingResource)geoprocessingResourceItem.Resource;

        ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingFunctionality commonGeoprocessingFunctionality =
            (ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingFunctionality)
            geoprocessingResource.CreateFunctionality(typeof
            (ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingFunctionality), null);

        ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.GeoprocessingFunctionality
            agsGeoprocessingFunctionality = commonGeoprocessingFunctionality as
            ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.GeoprocessingFunctionality;

        // Make sure the geoprocessing functionality is initialized
        if (!agsGeoprocessingFunctionality.Initialized)
            agsGeoprocessingFunctionality.Initialize();

        #endregion

        #region Prepare inputs and start the GP task

        // Set the name of the geoprocessing (GP) task
        string GPTaskName = "BufferPoints";

        // Get an array of the GP task's parameters
        ESRI.ArcGIS.ADF.Web.DataSources.GPToolInfo adfGPToolInfo =
            agsGeoprocessingFunctionality.GetTask(GPTaskName);
        ESRI.ArcGIS.ADF.Web.DataSources.GPParameterInfo[] adfGPParamterInfoArray =
            adfGPToolInfo.ParameterInfo;

        // Get a reference to the first input parameter (a feature set) as a Web ADF feature graphics layer
        ESRI.ArcGIS.ADF.Web.DataSources.GPFeatureGraphicsLayer adfGPFeatureGraphicsLayer =
            (ESRI.ArcGIS.ADF.Web.DataSources.GPFeatureGraphicsLayer)adfGPParamterInfoArray[0].Value;
        ESRI.ArcGIS.ADF.Web.Display.Graphics.FeatureGraphicsLayer featureGraphicsLayer =
            adfGPFeatureGraphicsLayer.Layer;

        // Get the graphics resource containing the layer that holds the user-placed points
        ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource adfGraphicsMapResource =
            Map1.GetFunctionality(_graphicsResourceName).Resource as
            ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource;

        // Get the graphics layer containing the user-placed points
        ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer pointElementGraphicsLayer =
            adfGraphicsMapResource.Graphics.Tables[_pointGraphicsLayerName] as
            ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer;

        // If there are no points in the layer, alert the user and exit the function
        if ((pointElementGraphicsLayer == null) || (pointElementGraphicsLayer.Rows.Count < 1))
        {
            ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult noPointsAlertCallbackResult =
                ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(
                "alert('No points to buffer')");
            _callbackResultCollection.Add(noPointsAlertCallbackResult);
            _callbackResultCollection.Add(HideActivityIndicators());
            return;
        }

        // Add each point to the feature graphics layer that we're using as input to the GP task
        foreach (System.Data.DataRow dataRow in pointElementGraphicsLayer.Rows)
        {
            ESRI.ArcGIS.ADF.Web.Geometry.Point adfPoint =
                pointElementGraphicsLayer.GeometryFromRow(dataRow) as
                ESRI.ArcGIS.ADF.Web.Geometry.Point;
            featureGraphicsLayer.Add(adfPoint);
        }

        // Get the Web ADF Unit enumeration value corresponding to the user-defined unit 
        ESRI.ArcGIS.ADF.Web.DataSources.GPLinearUnit adfGPLinearUnit =
            new ESRI.ArcGIS.ADF.Web.DataSources.GPLinearUnit();
        ESRI.ArcGIS.ADF.Web.DataSources.Units adfUnits =
            (ESRI.ArcGIS.ADF.Web.DataSources.Units)System.Enum.Parse(typeof(
            ESRI.ArcGIS.ADF.Web.DataSources.Units), units, true);

        // Set the GP task's second input parameter (linear unit) using the user-defined
        // distance and units 
        adfGPLinearUnit.Units = adfUnits;
        adfGPLinearUnit.Value = bufferDistance;

        // Put the parameters in an input array and start the geoprocessing job
        ESRI.ArcGIS.ADF.Web.DataSources.GPValue[] adfGPValueArray =
            new ESRI.ArcGIS.ADF.Web.DataSources.GPValue[2];
        adfGPValueArray[0] = adfGPFeatureGraphicsLayer;
        adfGPValueArray[1] = adfGPLinearUnit;
        string jobID = agsGeoprocessingFunctionality.SubmitJob(GPTaskName, adfGPValueArray);

        #endregion

        #region Construct a callback to check the GP task's status

        // Get the output parameter names to use when retrieving geoprocessing job results
        string outputParameters = null;
        ESRI.ArcGIS.ADF.Web.DataSources.GPParameterInfo agsGPParameterInfo;
        for (int i = 0; i < adfGPParamterInfoArray.Length; i++)
        {
            agsGPParameterInfo = adfGPParamterInfoArray[i];

            // Only append output parameters to the parameter string
            if (agsGPParameterInfo.Direction ==
                ESRI.ArcGIS.ADF.Web.DataSources.GPParameterDirection.Output)
            {
                outputParameters += agsGPParameterInfo.Name;
                if (i != adfGPParamterInfoArray.Length - 1)
                    outputParameters += ";";
            }
        }

    ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult checkJobStatusCallbackResult = 
      GetStatusCheckJavaScript(GPTaskName, jobID, outputParameters, 1000);

        _callbackResultCollection.Add(checkJobStatusCallbackResult);

        #endregion
    }

    // Check the GP job status for the job with the passed-in parameters and take action accordingly
    protected void CheckJobStatus(string jobID, string taskName, string outputParameters)
    {
        #region Initialize geoprocessing resources and functionalities

        // Initialize GP resource and functionality
        ESRI.ArcGIS.ADF.Web.UI.WebControls.GeoprocessingResourceItem geoprocessingResourceItem =
            GeoprocessingResourceManager1.ResourceItems.Find(_geoprocessingResourceName);

        // Make sure the geoprocessing resource is initialized
        if (!geoprocessingResourceItem.Resource.Initialized)
            geoprocessingResourceItem.InitializeResource();

        // Get a reference to the GP resource and its functionality
        ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingResource geoprocessingResource =
            (ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingResource)geoprocessingResourceItem.Resource;

        ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingFunctionality commonGeoprocessingFunctionality =
            (ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingFunctionality)
            geoprocessingResource.CreateFunctionality(typeof
            (ESRI.ArcGIS.ADF.Web.DataSources.IGeoprocessingFunctionality), null);

        ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.GeoprocessingFunctionality
            agsGeoprocessingFunctionality = commonGeoprocessingFunctionality as
            ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.GeoprocessingFunctionality;

        // Make sure the geoprocessing functionality is initialized
        if (!agsGeoprocessingFunctionality.Initialized)
            agsGeoprocessingFunctionality.Initialize();

        #endregion

        #region Construct callback to alert user if GP task failed or to check job status again if task is not complete

        // Get the GP job's status
        ESRI.ArcGIS.ADF.Web.DataSources.JobStatus adfJobStatus = agsGeoprocessingFunctionality.GetJobStatus(jobID);

        // If GP job failed, get job's last message and return it in an alert box
        if (adfJobStatus == ESRI.ArcGIS.ADF.Web.DataSources.JobStatus.Failed || 
            adfJobStatus == ESRI.ArcGIS.ADF.Web.DataSources.JobStatus.TimedOut)
        {
            // Get the GP job's messages
            ESRI.ArcGIS.ADF.Web.DataSources.JobMessage[] adfJobMessageArray = 
                agsGeoprocessingFunctionality.GetJobMessages(jobID);
            int messageCount = adfJobMessageArray.Length;

            // Create the alert javascript and package it in a callback
            string jsAlertGPError = string.Format("alert('GP job failed: {0}')",
                adfJobMessageArray[messageCount - 1].MessageDesc);
            ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult gpErrorAlertCallbackResult =
                ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsAlertGPError);

            // Add the error alert to the callback results collection
            _callbackResultCollection.Add(gpErrorAlertCallbackResult);

            // Add a callback result to hide the operation activity indicators to the callback results collection
            _callbackResultCollection.Add(HideActivityIndicators());
            return;
        }
        else if (adfJobStatus != ESRI.ArcGIS.ADF.Web.DataSources.JobStatus.Succeeded)
        {
            // Since the GP job is not yet complete, create the javascript necessary to trigger another callback
            // that will check the GP job status in 5 seconds.  Package this javascript in a callback result and
            // add it to the callback results collection
            _callbackResultCollection.Add(GetStatusCheckJavaScript(taskName, jobID, outputParameters, 5000));
            return;
        }

        #endregion

        #region Process the GP task's results

        // Parse the GP task's output parameter names
        string[] outputParametersArray = outputParameters.Split(';');
        // Get the result of the GP task
        ESRI.ArcGIS.ADF.Web.DataSources.GPResult adfGPResult =
            agsGeoprocessingFunctionality.GetJobResult(taskName, jobID, outputParametersArray, false);

        // Get the results of the GP operation
        ESRI.ArcGIS.ADF.Web.DataSources.GPValue[] adfGPValueArray = adfGPResult.Values;

        // Get the output feature set containing buffers as a Web ADF feature graphics layer
        ESRI.ArcGIS.ADF.Web.DataSources.GPFeatureGraphicsLayer adfGPFeatureGraphicsLayer =
            adfGPValueArray[0] as ESRI.ArcGIS.ADF.Web.DataSources.GPFeatureGraphicsLayer;
        ESRI.ArcGIS.ADF.Web.Display.Graphics.FeatureGraphicsLayer featureGraphicsLayer =
            adfGPFeatureGraphicsLayer.Layer;

        // If the graphics layer has no features, alert the user that the operation did not create 
        // any output
        if ((featureGraphicsLayer == null) || (featureGraphicsLayer.Rows.Count < 1))
        {
            ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult noResultsAlertCallbackResult =
                ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(
                "alert('No results returned');");
            _callbackResultCollection.Add(noResultsAlertCallbackResult);

            // Add a callback result to hide the operation activity indicators and enable the
            // Buffer Points button
            _callbackResultCollection.Add(HideActivityIndicators());
            return;
        }

        // Get the graphics layer's symbols and set their transparency to 50%
        System.Collections.Generic.List<ESRI.ArcGIS.ADF.Web.Display.Symbol.FeatureSymbol>
            featureSymbolList = new System.Collections.Generic.List<
                ESRI.ArcGIS.ADF.Web.Display.Symbol.FeatureSymbol>();
        featureGraphicsLayer.Renderer.GetAllSymbols(featureSymbolList);
        foreach (ESRI.ArcGIS.ADF.Web.Display.Symbol.FeatureSymbol featureSymbol in featureSymbolList)
            featureSymbol.Transparency = 50;

        // Set the buffer graphics layer's name
        featureGraphicsLayer.TableName = _bufferGraphicsLayerName;

        // Get the graphics resource to put the results layer in
        ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource graphicsMapResource =
            Map1.GetFunctionality(_graphicsResourceName).Resource as
            ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource;

        // If the resource already has a buffer graphics layer, remove it
        if (graphicsMapResource.Graphics.Tables.Contains(_bufferGraphicsLayerName))
            graphicsMapResource.Graphics.Tables.Remove(_bufferGraphicsLayerName);

        // Add new graphics layer to display the buffers
        graphicsMapResource.Graphics.Tables.Add(featureGraphicsLayer);

        // Refresh the graphics resource and copy the map's callback results to the callback collection
        // so the operation results are displayed
        Map1.RefreshResource(graphicsMapResource.Name);
        _callbackResultCollection.CopyFrom(Map1.CallbackResults);

        // Since the operation is complete, hide its activity indicators
        _callbackResultCollection.Add(HideActivityIndicators());

        #endregion
    }

    // Creates a callback result with the client-side code needed to hide the operation activity indicator
    // and enable the operation execution button
    private ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult HideActivityIndicators()
    {
        string jsHideIndicators = "toggleActivityIndicators(false);";
        ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult hideIndicatorsCallbackResult =
            ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsHideIndicators);
        return hideIndicatorsCallbackResult;
    }

    // Clears features from all graphics layers in the resource specified by _graphicsResourceName
    protected void ClearGraphics()
    {
        // Retrieve the resource and clear its graphics dataset
        ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource graphicsMapResource =
            Map1.GetFunctionality(_graphicsResourceName).Resource as
            ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource;
        graphicsMapResource.Graphics.Clear();

        // Refresh the resource and copy the map's callback results to the callback results collection so
        // the graphics are removed from the map
        Map1.RefreshResource(graphicsMapResource.Name);
        _callbackResultCollection.CopyFrom(Map1.CallbackResults);
  }

  private ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult GetStatusCheckJavaScript(
    string GPTaskName, string jobID, string outputParameters, int timeout)
  {
    string arguments =
      string.Format("EventArg=CheckJobStatus&JobID={0}&TaskName={1}&OutputParameters={2}",
      jobID, GPTaskName, outputParameters);
    // Construct a callback with the JavaScript needed to trigger a second callback after one second 
    // (1000 milliseconds) that will execute logic on the server to check the GP job's status and
    // take action accordingly
    string jsCheckJobStatus = 
      "window.setTimeout(\"ESRI.ADF.Samples.PostbackManager.doAsyncRequest('{0}');\",{1});";
    jsCheckJobStatus = string.Format(jsCheckJobStatus, arguments, timeout);
    ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult checkJobStatusCallbackResult =
      ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsCheckJobStatus);
    return checkJobStatusCallbackResult;
  }

    #endregion
}