ArcGIS Add Dynamic Data
ArcGIS_AddDynamicData_CSharp\RemoveLayer_ADF.aspx.cs
// Copyright 2009 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.
// 

// Illustrates how to remove an existing layer in a pooled ArcGIS Server map service using Web ADF components
// and ArcObjects. For illustration of how to add and remove a dynamic layer from a map service, see the 
// Default_ADF and CustomMapHandler_ADF pages. Note that this code bypasses use of the custom map handler (and
// the accompanying increase in map performance) by setting the Map1.EnableMapHandler property to false.
public partial class RemoveLayer_ADF : 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 =
        new ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResultCollection();
    private ServerObjectStateModifier m_serverObjectStateModifier = null;
    private System.Collections.Generic.Dictionary<int, ESRI.ArcGIS.Carto.ILayer> m_removedLayerDictionary = null;
    
    // Specify the name of the resource containing the layer to remove
    private string m_targetResourceName = "MapResourceItem0";
    // Specify the name of the layer to remove
    private string m_targetLayerName = "Highways";

    #endregion

    #region ASP.NET Page Life Cycle Event Handlers

    protected void Page_PreInit(object sender, System.EventArgs e)
    {
        // Instantiate a class-level ServerObjectStateModifier to use in removing and re-adding the layer
        m_serverObjectStateModifier = new ServerObjectStateModifier();
    }

    protected void Page_Load(object sender, System.EventArgs e)
    {
        try
        {
            // Define the parameters for a browser call to the WebForm_DoCallback JavaScript function
            // via the GetCallbackEventReference function.  The GetCallbackEventReference 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);

            // If the target layer has been removed (indicated by the session variable), then we need to re-remove it
            // so that the Web ADF components accessing the changed map resource is aware of the change.  
            if ((Session["LayerRemoved"] != null) && ((bool)Session["LayerRemoved"]))
            {
                // Get the layer's target resource and call the method to remove the layer from it
                ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality agsMapFunctionality =
                    (ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality)Map1.GetFunctionality(m_targetResourceName);
                ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal mapResourceLocal =
                    (ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal)agsMapFunctionality.Resource;
                m_removedLayerDictionary = m_serverObjectStateModifier.RemoveLayer(mapResourceLocal, m_targetLayerName);
            }

            MapResourceManager1.ResourcesDispose += new System.EventHandler(MapResourceManager1_ResourcesDispose);
        }
        catch (System.Exception exception)
        {
            // Check whether the page is loading as a result of a callback.  If not, assume that a full page postback
            // is occuring, since this page implements the callback framework (and not partial postback).
            if (Page.IsCallback)
            {
                // Get a callback result that will show an alert with information pertaining to the exception
                ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult errorCallbackResult =
                    Utility.GetErrorCallback(exception);
                // Get the control that initiated the postback
                System.Web.UI.Control control = Utility.GetPostBackControl(Page);

                // If the control is a Web ADF Control (i.e. WebCotnrol or CompositeControl), add the error 
                // callback to that control's callback results.  Otherwise, add the error callback to the 
                // callback results collection member variable, which will be passed to the client in 
                // GetCallbackResult.
                if (control is ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl)
                {
                    ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl adfWebControl = control as
                        ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl;
                    adfWebControl.CallbackResults.Add(errorCallbackResult);
                }
                else if (control is ESRI.ArcGIS.ADF.Web.UI.WebControls.CompositeControl)
                {
                    ESRI.ArcGIS.ADF.Web.UI.WebControls.CompositeControl adfCompositeControl = control as
                        ESRI.ArcGIS.ADF.Web.UI.WebControls.CompositeControl;
                    adfCompositeControl.CallbackResults.Add(errorCallbackResult);
                }
                else
                {
                    m_callbackResultCollection.Add(errorCallbackResult);
                }
            }
            else
            {
                // Since the page is in full postback, write the javascript alert code directly to the response
                string jsErrorAlert = string.Format("<script>{0}</script>",
                    Utility.GetJavaScriptErrorString(exception));
                Response.Write(jsErrorAlert);
            }
        }
    }

    #endregion

    #region Web ADF Control Event Handlers

    void MapResourceManager1_ResourcesDispose(object sender, System.EventArgs e)
    {
        // If the target layer has been removed (indicated by the session variable), then we need to add it back to the resource
        // before the server context created as a result of the current page request is released.  Otherwise, the target layer 
        // will be missing from the map service outside the scope of this request, so other clients using the service will not have
        // access to it.
        if ((Session["LayerRemoved"] != null) && ((bool)Session["LayerRemoved"]))
        {
            // Get the resource from which the layer was removed
            ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality agsMapFunctionality =
                (ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality)Map1.GetFunctionality(m_targetResourceName);
            ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal mapResourceLocal =
                (ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal)agsMapFunctionality.Resource;

            // Retrieve a reference to the missing layer and its original layer index from the class-level dictionary that
            // stored this information when the layer was removed
            System.Collections.Generic.Dictionary<int, ESRI.ArcGIS.Carto.ILayer>.Enumerator removedLayerEnumerator = 
                m_removedLayerDictionary.GetEnumerator();
            removedLayerEnumerator.MoveNext();
            ESRI.ArcGIS.Carto.IGeoFeatureLayer removedGeoFeatureLayer = removedLayerEnumerator.Current.Value as
                ESRI.ArcGIS.Carto.IGeoFeatureLayer;
            int layerIndex = removedLayerEnumerator.Current.Key;
            
            // Add the layer back to the map service
            m_serverObjectStateModifier.AddLayer(mapResourceLocal, removedGeoFeatureLayer, layerIndex);
        }
    }

    #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)
    {
        try
        {
            // Parse the callback string passed from the client to the server into separate
            // arguments using the Web ADF's callback parsing utility.
            System.Collections.Specialized.NameValueCollection callbackArgsCollection =
                ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(eventArgs);

            // Check whether the callback's event argument
            switch (callbackArgsCollection["EventArg"])
            {
                case "removeLayer":
                    // Check whether the session variable indicating that the layer has been removed has been populated.  If not, then
                    // the layer is still in the service and needs to be removed.
                    if (Session["LayerRemoved"] == null)
                    {
                        Session["LayerRemoved"] = true;

                        // Get the layer's target resource and call the method to remove the layer from it
                        ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality agsMapFunctionality =
                            (ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality)Map1.GetFunctionality(m_targetResourceName);
                        ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal mapResourceLocal =
                            (ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal)agsMapFunctionality.Resource;

                        // Store a reference to the dictionary containing the layer and its index in the map service
                        m_removedLayerDictionary = m_serverObjectStateModifier.RemoveLayer(mapResourceLocal, m_targetLayerName);

                        // Refresh the Map and Toc so they reflect the layer's removal
                        RefreshMapAndToc();
                    }
                    break;
            }
        }
        catch (System.Exception exception)
        {
            // Get a callback result that will alert the user of the error and add it to the callback results collection
            ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult errorCallbackResult =
                Utility.GetErrorCallback(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

    // Property allowing client-side access to the client callback function string.  This string
    // contains the necessary JavaScript syntax to initiate a callback with the parameters specified
    // in GetCallbackEventReference (in Page_Load).
    public string AdfCallbackFunctionString
    {
        get
        {
            return m_adfCallbackFunctionString;
        }
        set
        {
            m_adfCallbackFunctionString = value;
        }
    }

    #endregion

    #region Instance Methods

    // Refreshes the Map and Toc controls and populates the callback results member variable with the
    // resulting callback results 
    private void RefreshMapAndToc()
    {
        Toc1.Refresh();
        Map1.CallbackResults.CopyFrom(Toc1.CallbackResults);

        Map1.RefreshResource(m_targetResourceName);
        m_callbackResultCollection.CopyFrom(Map1.CallbackResults);
    }

    #endregion
}