ArcGIS ClipShip Geoprocessing
ArcGIS_ClipShip_Geoprocessing_CSharp\Default.aspx.cs
// Copyright 2008 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, System.Web.UI.ICallbackEventHandler
{
    #region Instance Variable Declarations

    private string m_adfCallbackFunctionString;
    private ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResultCollection m_callbackResultCollection;
    
    // Names of the layers that will hold the clipped features and user-drawn polylines
    private string m_clippedFeaturesLayerName = "Clip";
    private string m_polylineGraphicsLayerName = "Polylines";
    
    // Name of the geoproccessing resource containing the ClipCounties task
    private string m_geoprocessingResourceName = "Buffer and Clip Resource";

    // Name of the resource that will store clip results if m_displayResultsInMapResource is
    // set to true
    private string m_resultsMapResourceName = "Clip Results";
    
    // Name of the resource in which to store geoprocessing results (if 
    // m_displayResultsInMapResource is false) and user-drawn polylines
    private string m_graphicsResourceName = "Web ADF Graphics";

    // Determines whether to display the geoprocessing results in a map resource or as graphics
    private bool m_displayResultsInMapResource = true;

    // Name of the GP tool layer in the map service.  This is the layer that was created in the
    // underlying mxd by dragging and dropping the GP tool into the mxd.  This name will be used
    // to remove the layer from the Toc.
    private string m_toolLayerName = "ClipCounties";

    #endregion

    #region ASP.NET Page Life Cycle Event Handlers

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

            // Make sure control initialization only occurs during initial page load or on page refresh
            if (!Page.IsPostBack)
            {
                // 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);
        }
    }

    // Generates custom callback function string for non-ADF controls\elements in page that generate callbacks
    protected void Page_Load(object sender, System.EventArgs e)
    {
        // Define the parameters for a browser call to the WebForm_DoCallback JavaScript function
        // via the GetCallbackEventReference function.  This function returns the syntax for initiating 
        // a callback (i.e a call to WebForm_DoCallback) with the passed-in parameters.  Here the 
        // parameters are defined as follows:
        // this - the Page will handle the callback request
        // "message" - a JavaScript variable named "message" will contain argument-value pairs passed 
        //      to the callback server-side
        // "processCallbackResult" - name of the JavaScript function to process the callback 
        //      results from the server.  This function is the callback results handler included with 
        //      the Web ADF JavaScript Library.
        // "context" - a JavaScript variable named "context" which can be used by the client to
        //      indicate the origin of the callback
        // "postBackError" - name of the JavaScript function that will process errors returned during 
        //      callback processing.  This is the callback error handler included with the Web ADF 
        //      JavaScript Library
        // true - define whether the callback is synchronous or asynchronous.  True is asynchronous.        
        m_adfCallbackFunctionString = Page.ClientScript.GetCallbackEventReference(this, "message", 
            "processCallbackResult", "context", "postBackError", true);

        RemoveLayerFromToc(m_toolLayerName);
    }

    #endregion

    #region ICallbackEventHandler Members

    // Receives the arguments packaged in the callback on the client.  We parse those arguments here and 
    // initiate server-side logic accordingly.
    public void RaiseCallbackEvent(string eventArgs)
    {
        // Instantiate a new callback results collection to hold the callback's results
        m_callbackResultCollection =
            new ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResultCollection();

        try
        {
            // Use the Web ADF's callback utility to parse the arguments into a NameValueCollection
            System.Collections.Specialized.NameValueCollection callbackArgsNameValueCollection =
                ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(eventArgs);

            // Check the callback event argument and execute logic accordingly
            string eventArg = callbackArgsNameValueCollection["EventArg"];
            string downloadOutputString = null;
            bool downloadOutput = false;
            switch (eventArg)
            {
                case "bufferAndClip":
                    // Get the user-specified buffer and clip operation parameters
                    string bufferDistanceString = callbackArgsNameValueCollection["BufferDistance"];
                    double bufferDistance = 0;
                    double.TryParse(bufferDistanceString, out bufferDistance);
                    downloadOutputString = callbackArgsNameValueCollection["DownloadOutput"];
                    bool.TryParse(downloadOutputString, out downloadOutput);

                    // Invoke the method to initiate the geoprocessing task
                    StartBufferAndClipJob(bufferDistance, callbackArgsNameValueCollection["Units"], downloadOutput);
                    break;
                case "clearGraphics":
                    // Invoke the method to clear the graphics from the map
                    ClearGraphics();
                    break;
                case "checkGeoprocessingJob":
                    // Get parameter indicating whether geoprocessing results are to be made available for download
                    downloadOutputString = callbackArgsNameValueCollection["DownloadOutput"];
                    bool.TryParse(downloadOutputString, out downloadOutput);

                    // Check whether the geoprocssing job is finished and process results if so
                    CheckGeoprocessingJobStatus(callbackArgsNameValueCollection["JobID"],
                        callbackArgsNameValueCollection["TaskName"],
                        callbackArgsNameValueCollection["TaskOutputParameters"], downloadOutput);
                    break;
            }
        }
        catch (System.Exception exception)
        {
            ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult errorCallbackResult =
                Utility.CreateErrorCallbackResult(exception);
            m_callbackResultCollection.Add(errorCallbackResult);
        }
    }

    // The last server-side method called before the callback returns to the browser, GetCallbackResult
    // is where the server-side result of the callback is passed back to the browser as a string for
    // processing by the client.
    public string GetCallbackResult()
    {
        return m_callbackResultCollection.ToString();
    }


    #endregion

    #region Instance Properties

    // Provides a client-side reference to the function call that will initiate a callback to this page
    public string AdfCallbackFunctionString
    {
        get { return m_adfCallbackFunctionString; }
    }

    #endregion

    #region Instance Methods

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

        // Initialize GP resource and functionality
        ESRI.ArcGIS.ADF.Web.UI.WebControls.GeoprocessingResourceItem geoprocessingResourceItem =
            GeoprocessingResourceManager1.ResourceItems.Find(m_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 = "ClipCounties";

        // 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-drawn lines
        ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource adfGraphicsMapResource = 
            Map1.GetFunctionality(m_graphicsResourceName).Resource as 
            ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource;

        // Get the graphics layer containing the user-drawn lines
        ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer polylineElementGraphicsLayer =
            adfGraphicsMapResource.Graphics.Tables[m_polylineGraphicsLayerName] as
            ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer;

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

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

        // 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 outputTaskParameters = 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)
            {
                // Only append the zip file parameter name if the user has checked the download
                // checkbox
                if (agsGPParameterInfo.Name == "output_zip" && !downloadOutput)
                    continue;

                outputTaskParameters += agsGPParameterInfo.Name;
                if (i != adfGPParamterInfoArray.Length - 1)
                    outputTaskParameters += ";";
            }
        }

        // 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 jsCheckGeoprocessingJob = string.Format("window.setTimeout('executeCallback(" +
            "\"checkGeoprocessingJob\", \"JobID={0}&TaskName={1}&TaskOutputParameters={2}&" +
            "DownloadOutput={3}\")',1000);", jobID, GPTaskName,outputTaskParameters, downloadOutput.ToString());
        ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult checkGeoprocessingJobCallbackResult = 
            ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsCheckGeoprocessingJob);

        // Add the GP job status check callback to the callback results collection
        m_callbackResultCollection.Add(checkGeoprocessingJobCallbackResult);

        #endregion
    }

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

        // Initialize GP resource and functionality
        ESRI.ArcGIS.ADF.Web.UI.WebControls.GeoprocessingResourceItem geoprocessingResourceItem =
            GeoprocessingResourceManager1.ResourceItems.Find(m_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
            m_callbackResultCollection.Add(gpErrorAlertCallbackResult);

            // Add a callback result to hide the operaton activity indicators to the callback results collection
            m_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
            string jsCheckGeoprocessingJob = string.Format("window.setTimeout('executeCallback(" +
                "\"checkGeoprocessingJob\", \"JobID={0}&TaskName={1}&TaskOutputParameters={2}&" +
                "DownloadOutput={3}\")',5000);", jobID, taskName, taskOutputParameters, downloadOutput.ToString());
            ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult checkGeoprocessingJobCallbackResult =
                ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsCheckGeoprocessingJob);
            m_callbackResultCollection.Add(checkGeoprocessingJobCallbackResult);
            return;
        }

        #endregion

        #region Process the GP task's results

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

        // Iterate through the GP task results.  If the result is a data file and the user
        // has checked the download results checkbox, add a callback that will enable 
        // downloading of this file.  If the result is a graphics layer or a map resource
        // definition, add the contents of these to the map so the results are displayed.
        ESRI.ArcGIS.ADF.Web.DataSources.GPValue[] adfGPValueArray = adfGPResult.Values;
        foreach (ESRI.ArcGIS.ADF.Web.DataSources.GPValue adfGPValue in adfGPValueArray)
        {
            if (adfGPValue is ESRI.ArcGIS.ADF.Web.DataSources.GPDataFile && downloadOutput)
            {
                #region Make the results available for download

                // Get the URL of the data file
                ESRI.ArcGIS.ADF.Web.DataSources.GPDataFile adfGPDataFile =
                    (ESRI.ArcGIS.ADF.Web.DataSources.GPDataFile)adfGPValue;
                string urlZipFileString = adfGPDataFile.Data.URL;

                // Construct JavaScript to insert an iframe into the page that has the data file url 
                // as its source.  The iframe will attempt to load whatever is referenced as its
                // source, which in this case will trigger a download dialog.
                string jsDynamicDownload = "var ifrm = document.createElement('IFRAME');" +
                    "ifrm.setAttribute('src','{0}');" +
                    "ifrm.style.width='0px';" +
                    "ifrm.style.height='0px';" +
                    "ifrm.style.visibility='hidden';" +
                    "document.body.appendChild(ifrm);";                
                jsDynamicDownload = string.Format(jsDynamicDownload, urlZipFileString);

                // Package the download-triggering JavaScript in a callback and add to the callback results
                ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult dynamicDownloadCallbackResult =
                    ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsDynamicDownload);
                m_callbackResultCollection.Add(dynamicDownloadCallbackResult);

                #endregion
            }
            else if (adfGPValue is ESRI.ArcGIS.ADF.Web.DataSources.GPFeatureGraphicsLayer)
            {
                #region Add the clipped features to the map as graphics

                // The clip results will be returned as a feature graphics layer if 
                // m_displayResultsInMapResource is set to false
                
                // Get output feature set containing buffers as a Web ADF feature graphics layer
                ESRI.ArcGIS.ADF.Web.DataSources.GPFeatureGraphicsLayer adfGPFeatureGraphicsLayer =
                    adfGPValue 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');");
                    m_callbackResultCollection.Add(noResultsAlertCallbackResult);

                    // Add a callback result to hide the operation activity indicators and enable the
                    // Buffer and Clip button
                    m_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 feature graphics layer's name
                featureGraphicsLayer.TableName = m_clippedFeaturesLayerName;

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

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

                // Add new graphics layer to display new 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);
                m_callbackResultCollection.CopyFrom(Map1.CallbackResults);

                #endregion
            }
            else if (adfGPValue is ESRI.ArcGIS.ADF.Web.DataSources.GPMapResourceDefinition)
            {
                #region Add the clipped features to the map as features                
                
                // The clip results will be returned in a map resource definition if 
                // m_displayResultsInMapResource is set to true.
                //
                // Note that the code here makes use of the map resource definition created from the
                // GP results by the Web ADF.  For more information on how to associate GP results 
                // and ArcGIS Server map resources, see the LayerDescription help.
                
                // Get the GP map resource definition 
                ESRI.ArcGIS.ADF.Web.DataSources.GPMapResourceDefinition gpMapResourceDefinition =
                    adfGPValue as ESRI.ArcGIS.ADF.Web.DataSources.GPMapResourceDefinition;

                // Check whether a results map resource item has already been added
                ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem mapResourceItem =
                    MapResourceManager1.ResourceItems.Find(m_resultsMapResourceName);
                if (mapResourceItem == null)
                {
                    // Create a new map resource item to hold the results since one doesn't yet exist

                    // Instantiate the map resource item with the name specified in the class member.
                    mapResourceItem = new ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem();
                    mapResourceItem.Name = m_resultsMapResourceName;

                    // Apply the GP results resource definition to the map resource item
                    mapResourceItem.Definition = new
                        ESRI.ArcGIS.ADF.Web.UI.WebControls.GISResourceItemDefinition(gpMapResourceDefinition.Value);

                    // Initialize the map resource item's display properties
                    ESRI.ArcGIS.ADF.Web.DisplaySettings displaySettings = new ESRI.ArcGIS.ADF.Web.DisplaySettings();
                    displaySettings.Transparency = 50;
                    displaySettings.Visible = true;
                    displaySettings.ImageDescriptor.TransparentColor = System.Drawing.Color.White;
                    displaySettings.ImageDescriptor.TransparentBackground = true;
                    mapResourceItem.DisplaySettings = displaySettings;

                    // Add the new map resource item to the resource manager
                    MapResourceManager1.ResourceItems.Insert(0, mapResourceItem);

                    // Refresh the Toc and copy its callback results to the callback results collection so the new
                    // resource has a Toc node
                    Toc1.Refresh();
                    m_callbackResultCollection.CopyFrom(Toc1.CallbackResults);
                }
                else
                {
                    // Since the map resource item to hold the results has already been created, simply apply
                    // the definition returned with the GP results
                    mapResourceItem.Definition = new
                        ESRI.ArcGIS.ADF.Web.UI.WebControls.GISResourceItemDefinition(gpMapResourceDefinition.Value);
                }

                // Refresh the results resource and copy the map's callback results to the callback results 
                // collection so the result features are displayed on the map
                Map1.RefreshResource(m_resultsMapResourceName);
                m_callbackResultCollection.CopyFrom(Map1.CallbackResults);

                #endregion
            }
        }

        m_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 m_graphicsResourceName
    private void ClearGraphics()
    {
        // Retrieve the resource and clear its graphics dataset
        ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource graphicsMapResource =
            Map1.GetFunctionality(m_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);
        m_callbackResultCollection.CopyFrom(Map1.CallbackResults);
    }


    // Removes the layer matching the input name from the TOC
    private void RemoveLayerFromToc(string layerName)
    {
        // Iterate through the nodes at the top level of the Toc.  Each of these should correspond to a resource.
        foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode resourceTreeViewPlusNode in
            Toc1.Nodes)
        {
            ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode treeViewPlusNodeToRemove = null;

            // Iterate through the nodes below the current top-level node.  Each of these should 
            // correspond to a layer.
            foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode layerTreeViewPlusNode in
                resourceTreeViewPlusNode.Nodes)
            {
                // Attempt to retrieve a node with text matching the passed-in layer name.  This could be
                // the current node or any node below it.  Note that we need to search both the current node
                // and any child nodes to handle group layers.
                ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode matchingTreeViewPlusNode =
                    Utility.FindNodeRecursive(layerTreeViewPlusNode, layerName);

                // If a matching node was found, store a reference to it to be accessed outside the loop
                if (matchingTreeViewPlusNode != null)
                {
                    treeViewPlusNodeToRemove = matchingTreeViewPlusNode;
                    break;
                }
            }

            // Remove the matching node, if found
            if (treeViewPlusNodeToRemove != null)
                treeViewPlusNodeToRemove.Remove();
        }
    }
    #endregion
}