Common Security
Common_Security_CSharp\App_Code\GetMapInformation.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.
// 


namespace CustomComponents
{
    public class GetMapInformation : ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools.IMapServerCommandAction
    {
        #region IServerAction Members

        // Executes the action for the command. Gets information about the map's layers, packages that 
        // information as a callback result, and passes the callback result back to the client for display.
        void ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools.IServerAction.ServerAction(
            ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools.ToolbarItemInfo toolbarItemInfo)
        {
            // Get a reference to the map control to which the toolbar is buddied
            ESRI.ArcGIS.ADF.Web.UI.WebControls.Map adfMap =
                (ESRI.ArcGIS.ADF.Web.UI.WebControls.Map)toolbarItemInfo.BuddyControls[0];

            try
            {
                // Get map/layer/field information via private method
                string mapInfoHtml = GetMapAndLayerInformation(adfMap);

                // Create a callback result that will replace the content of a div tag in the page with the 
                // map information.  The "HtmlGenericControl" paramter indicates the type of control to be
                // updated.  The "divMapInfo" parameter indicates the ID of the control to be updated; 
                // divMapInfo is a <div> element on the Default.aspx page.  The "innercontent" parameter
                // specifies that the HTML content of the specified control is to be updated.  The mapInfoHtml
                // parameter specifies the content with which we wish to update the specified control.
                ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult callbackResult =
                    ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateSetInnerContent(
                        "divMapInfo", mapInfoHtml);

                // add the callback result to the map's results so they will get
                //  passed to the page
                adfMap.CallbackResults.Add(callbackResult);
            }
            catch (System.Exception exception)
            {
                ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult errorCallbackResult =
                    Utility.GetErrorCallback(exception);
                adfMap.CallbackResults.Add(errorCallbackResult);    
            }
        }

        #endregion

        #region Instance Methods

        // Retrieves information about map services, layers, and fields for vector layers, and returns 
        // this information as an HTML-formatted string.
        private string GetMapAndLayerInformation(ESRI.ArcGIS.ADF.Web.UI.WebControls.Map adfMap)
        {
            // make sure map resources are initialized
            if (!adfMap.InitializedFunctionalities)
                adfMap.InitializeFunctionalities();

            // Intantiate a string builder object to use in creating the HTML markup.  Initialize the string builder
            // with a title for the map information.
            System.Text.StringBuilder mapInfoStringBuilder =
                new System.Text.StringBuilder("<h2>Map Information:</h2>");

            string[] fieldNames, layerIDs, layerNames;

            // loop through each map service
            foreach (ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality commonMapFunctionality 
                in adfMap.GetFunctionalities())
            {
                // Add the resource definition and name to the map information HTML
                ESRI.ArcGIS.ADF.Web.DataSources.IGISResource gisResource = commonMapFunctionality.Resource;
                mapInfoStringBuilder.AppendFormat("<h3>Service: {0} ({1})</h3>",
                    gisResource.ResourceDefinition, gisResource.Name);

                // Check whether the current resource supports ADF QueryFunctionality.  We need this to access the 
                // fields of vector layers
                if (gisResource.SupportsFunctionality(typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)))
                {
                    ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality commonQueryFunctionality =
                        (ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)gisResource.CreateFunctionality(
                        typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), null);

                    // Get layer IDs and names
                    commonQueryFunctionality.GetQueryableLayers(null, out layerIDs, out layerNames);

                    // Iterate through the layer IDs
                    for (int i = 0; i < layerIDs.Length; i++)
                    {
                        // Add the current layer's name to the map information HTML
                        mapInfoStringBuilder.AppendFormat("<h4>Layer {0}</h4>Fields:<br/>", layerNames[i]);

                        // Retrieve and iterate through the field names of the current layer
                        fieldNames = commonQueryFunctionality.GetFields(null, layerIDs[i]);
                        foreach (string fieldName in fieldNames)
                        {
                            // Add the name of the current field to the map information HTML
                            mapInfoStringBuilder.AppendFormat("{0}<br/>", fieldName);
                        }
                        mapInfoStringBuilder.Append("<br>");
                    }
                }
                mapInfoStringBuilder.Append("<br>");
            }
            return mapInfoStringBuilder.ToString();
        }

        #endregion
    }

    public class Utility
    {
        // Constructs a callback result that will display an error message based on the passed-in
        // exception
        public static ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult GetErrorCallback(
            System.Exception exception)
        {
            // Create a callback result to display an error message
            string jsAlertErrorMessage = GetJavaScriptErrorString(exception);
            ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult alertCallbackResult =
                ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsAlertErrorMessage);
            return alertCallbackResult;
        }

        // Constructs JavaScript necessary to display an error message based on the passed-in exception.
        public static string GetJavaScriptErrorString(System.Exception exception)
        {
            // Get the website's configuration file
            System.Configuration.Configuration webConfig =
            System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(
                System.Web.HttpContext.Current.Request.ApplicationPath);

            // Get the "compilation" section of the config file
            System.Web.Configuration.CompilationSection compilationSection =
                webConfig.GetSection("system.web/compilation") as
                System.Web.Configuration.CompilationSection;

            // If the config file's compilation section specifies debug mode, include 
            // stack trace information in the error message.  Otherwise, just return 
            // the exception message.
            string errorMessage = null;
            if ((compilationSection != null) && (compilationSection.Debug))
            {
                string stackTrace = exception.StackTrace.Replace("\\", "\\\\");
                stackTrace = stackTrace.Replace("\n", "\\n");
                stackTrace = stackTrace.Replace("\r", "\\r");
                errorMessage = exception.Message + "\\n\\n" + stackTrace.Trim();
            }
            else
                errorMessage = exception.Message;

            // Create a callback result to display an error message
            string jsAlertException = "alert('" + errorMessage + "')";
            return jsAlertException;
        }

        // Gets the ID of the layer matching the input layer name.
        public static string GetLayerID(string layerName,
            ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality mapFunctionality)
        {
            string layerID = string.Empty;

            // get layerIDs and names from the passed-in map functionality
            string[] layerIDs, layerNames;
            mapFunctionality.GetLayers(out layerIDs, out layerNames);

            // Loop through the layer names.  If one of the names matches the passed-in layer name,
            // get that layer's ID and exit the loop.
            for (int i = 0; i < layerIDs.Length; i++)
            {
                if (layerNames[i] == layerName)
                {
                    layerID = layerIDs[i];
                    break;
                }
            }
            return layerID;
        }

        // Finds the node having the passed-in name from among the input node or its child nodes. 
        // Useful for searching a Toc with group layers.
        public static ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode FindNodeRecursive(
            ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode treeViewPlusNode, string nodeName)
        {
            // Check whether the text of the passed-in node matches the text sought.  Return the node if so.
            if (treeViewPlusNode.Text == nodeName)
                return treeViewPlusNode;

            // Iterate through the passed-in node's child nodes, calling this function on each.
            foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode childTreeViewPlusNode in treeViewPlusNode.Nodes)
            {
                ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode childNode =
                    FindNodeRecursive(childTreeViewPlusNode, nodeName);
                if (childNode != null)
                    return childNode;
            }

            // If the code reaches this point, no match was found. 
            return null;
        }

        // Retrieves the first control of the passed-in type from the passed-in control collection
        public static System.Web.UI.Control FindControlOfType(System.Type type,
            System.Web.UI.ControlCollection controlCollection)
        {
            // Iterate through all the controls in the passed-in control collection
            foreach (System.Web.UI.Control webControl in controlCollection)
            {
                // If the current control is of the passed-in type, return it.
                if (type.IsInstanceOfType(webControl))
                    return webControl;
                else if (webControl.HasControls())
                {
                    // The current control has child controls, so call this function on those child controls
                    System.Web.UI.Control childWebControl = FindControlOfType(type, webControl.Controls);
                    if (childWebControl != null)
                        return childWebControl;
                }
            }

            // If the code reaches this point, no match was found. 
            return null;
        }

        // Finds a control by checking whether the passed-in control or any child controls have an ID matching the 
        // passed-in control ID
        public static System.Web.UI.Control FindControlRecursive(System.Web.UI.Control webControl, string controlID)
        {
            // If the passed-in control has an ID that matches the passed-in ID, return it
            if (webControl.ID == controlID)
                return webControl;

            // Iterate through the child control's of the current control, calling this function on each
            foreach (System.Web.UI.Control childWebControl in webControl.Controls)
            {
                System.Web.UI.Control matchingControl = FindControlRecursive(childWebControl, controlID);
                if (matchingControl != null)
                {
                    return matchingControl;
                }
            }

            // If the code reaches this point, no match was found. 
            return null;
        }
    }
}