Common Custom EditorTask
Common_CustomEditorTask_CSharp\CustomEditorTaskWebApp_CSharp\StandardEditorTaskPage.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 StandardEditorTaskPage : System.Web.UI.Page
{
   
    #region ASP.NET Page Life Cycle Event Handlers

   protected void Page_Load(object sender, System.EventArgs e)
    {
        if (!this.Page.IsPostBack)
        {
            EditorTask1.EditorPanelsCreated +=
                 new ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditorPanelsCreatedEventHandler(EditorTask1_EditorPanelsCreated);
            EditorTask1.ToolsCreated +=
                new ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.ToolsCreatedEventHandler(EditorTask1_ToolsCreated);

            EditorTask1.PreAttributeEdit +=
                new ESRI.ArcGIS.ADF.ArcGISServer.Editor.PreAttributeEditEventHandler(EditorTask1_PreAttributeEdit);
            EditorTask1.PostAttributeEdit +=
                new ESRI.ArcGIS.ADF.ArcGISServer.Editor.PostAttributeEditEventHandler(EditorTask1_PostAttributeEdit);

            EditorTask1.PreCommandExecute +=
                new ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.PreCommandExecuteEventHandler(EditorTask1_PreCommandExecute);

            // Uncomment following if required to set attribute filtering parameters for the EditorTask during the 
            // Page Load event of the initial request.
            
            //    FilterAttributes();
            
        }
    }

    protected void Page_PreRender(object sender, System.EventArgs e)
    {
        if (!this.Page.IsPostBack)
        {
            // Determine whether the MapResourceManager has non-pooled resources and store in session
            Session["HasNonPooledResources"] = HasNonPooledResources();
        }
    }

    #endregion

 

    #region Web ADF EditorTask Event Handlers

    void EditorTask1_PreCommandExecute(object sender, 
        ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.PreCommandExecuteEventArgs preCommandExecuteEventArgs)
    {
        // Cancel the DeleteFeature command if the active edit layer is AddressPoints
        string commandName = preCommandExecuteEventArgs.ServerAction.ToolbarItemInfo.Name;
        string datasetName = preCommandExecuteEventArgs.ServerAction.DataSet.Name;
        //if (commandName.Equals("DeleteFeature") && datasetName.Equals("EditParcels.DBO.AddressPoints"))
        if (commandName.Equals("DeleteFeature") && datasetName.Equals("Montgomery.DBO.Parcels"))
        {
            preCommandExecuteEventArgs.Cancel = true;
            preCommandExecuteEventArgs.ReturnMessage = "Cannot delete features in " + datasetName;
        }
    }

    void EditorTask1_PreAttributeEdit(object sender, 
        ESRI.ArcGIS.ADF.ArcGISServer.Editor.PreAttributeEditEventArgs preAttributeEditEventArgs)
    {
        // If the an attribute is edited, check the fields of the feature being edited
        // for a field named "UPDATEDBY".  If present, and the current user is authenticated,
        // set the value of the field to the user name.
        int fieldIndex = preAttributeEditEventArgs.Feature.Table.FindField("UPDATEDBY");

        if (fieldIndex > -1)
        {
            string authenticatedUserName = Context.User.Identity.Name;
            if (!string.IsNullOrEmpty(authenticatedUserName))
                preAttributeEditEventArgs.Feature.set_Value(fieldIndex, authenticatedUserName);
        }
    }

    void EditorTask1_PostAttributeEdit(object sender, 
        ESRI.ArcGIS.ADF.ArcGISServer.Editor.PostAttributeEditEventArgs postAttributeEditEventArgs)
    {
        // If an attribute edit is unsuccessful, return exception message in a browser alert dialog.
        if (!postAttributeEditEventArgs.Successful)
            postAttributeEditEventArgs.ReturnMessage = postAttributeEditEventArgs.Exception.Message;
    }

    void EditorTask1_EditorPanelsCreated(object sender, 
        ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditorPanelsCreatedEventArgs editorPanelsCreatedEventArgs)
    {
        // Create instance of new Editor Panel that contains a CreateFeature tool
        CustomCreateFeaturePanel newCreateFeaturePanel = new CustomCreateFeaturePanel(EditorTask1);

        // Insert at the beginning (top) of the panels collection in the Editor
        editorPanelsCreatedEventArgs.EditorPanels.Insert(0, newCreateFeaturePanel);


        // If using the out-of-the-box EditorTask and CreateFeature tool,
        // the exiting CreateFeaturePanel cannot be removed.   The CreateFeature tool
        // uses the FeatureLabel property on the CreateFeaturePanel returned from Editor.NewFeatureCreator.
        //e.EditorPanels.Remove(editorPanel);
        ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditorPanel editorPanel =
            newCreateFeaturePanel.ParentEditor.NewFeatureCreator;
        editorPanel.Visible = false;
    }

    void EditorTask1_ToolsCreated(object sender, 
        ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.ToolsCreatedEventArgs toolsCreatedEventArgs)
    {
        if (toolsCreatedEventArgs.Parent == EditorTask1.Editor.ExistingFeatureEditor)
        {
            // The out-of-the-box EditExistingFeaturePanel contains two toolbars: GeometryToolbar1 and GeometryToolbar2
            foreach (ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.EditorToolbar editorToolbar in toolsCreatedEventArgs.Toolbars)
            {
                if (editorToolbar.ID == "GeometryToolbar1")
                {
                    // Add custom Clip tool to the GeometryToolbar1 toolbar in the EditExistingFeaturePanel
                    ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.EditorTool clipEditorTool =
                        new ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.EditorTool("Clip",
                        ((ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditExistingFeaturePanel)toolsCreatedEventArgs.Parent).ParentEditor.MapID, false,
                        ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.ToolGeometry.Line | ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.ToolGeometry.Polygon, 1);
                    clipEditorTool.ClientAction = ESRI.ArcGIS.ADF.Web.UI.WebControls.Constants.HTML_DRAG_RECTANGLE;
                    clipEditorTool.DefaultImage = "~/images/clip.png";
                    clipEditorTool.SelectedImage = "~/images/clip_ON.png";
                    clipEditorTool.HoverImage = "~/images/clip_OVER.png";
                    clipEditorTool.ToolTip = "Clip feature(s)";                    
                    clipEditorTool.ServerActionAssembly = "App_Code";
                    clipEditorTool.ServerActionClass = "CustomEditorTools.ClipFeatures";

                    editorToolbar.ToolbarItems.Add(clipEditorTool);
                    
                    // Resize the toolbar to accommodate the new tool.
                    editorToolbar.Width = new System.Web.UI.WebControls.Unit(
                        editorToolbar.Width.Value + 35, System.Web.UI.WebControls.UnitType.Pixel);
                }
            }

            // Add a new EditorToolbar to the EditExistingFeaturesPanel.  The EditorToolbar will 
            // automatically set the toolbar group to other EditorToolbars in the Editor.
            ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.EditorToolbar newEditorToolbar =
                new ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.EditorToolbar();
            newEditorToolbar.ToolbarStyle = ESRI.ArcGIS.ADF.Web.UI.WebControls.ToolbarStyle.ImageOnly;
            newEditorToolbar.ID = "MyCustomToolbar";
            newEditorToolbar.BuddyControlType = ESRI.ArcGIS.ADF.Web.UI.WebControls.BuddyControlType.Map;
            newEditorToolbar.BuddyControls.Add(new ESRI.ArcGIS.ADF.Web.UI.WebControls.BuddyControl(
                ((ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditExistingFeaturePanel)toolsCreatedEventArgs.Parent).ParentEditor.MapID));

            ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.EditorCommand verticeCountEditorCommand =
                new ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.EditorCommand("VerticeCount", 
                    ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.ToolGeometry.All, 1);
            verticeCountEditorCommand.DefaultImage = "~/images/verticecount.png";
            verticeCountEditorCommand.SelectedImage = "~/images/verticecount_ON.png";
            verticeCountEditorCommand.HoverImage = "~/images/verticecount_OVER.png";
            verticeCountEditorCommand.ToolTip = "Count the number of vertices in the selected feature";
            verticeCountEditorCommand.ServerActionAssembly = "App_Code";
            verticeCountEditorCommand.ServerActionClass = "CustomEditorTools.VerticeCount";

            newEditorToolbar.ToolbarItems.Add(verticeCountEditorCommand);
            // If Width is 0, JavaScript error Toolbars[..] is null
            newEditorToolbar.Width = new System.Web.UI.WebControls.Unit(newEditorToolbar.ToolbarItems.Count * 35, 
                System.Web.UI.WebControls.UnitType.Pixel);

            toolsCreatedEventArgs.Toolbars.Add(newEditorToolbar);
        }
    }

    #endregion

    #region Instance Methods

    private void FilterAttributes()
    {
        // Get the ArcGIS Server Local MapFunctionality associated with the EditorTask
        ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality agsLocalMapFunctionality =
            EditorTask1.Editor.MapFunctionality;

        string[] layerIDs = null;
        string[] layerNames = null;
        agsLocalMapFunctionality.GetLayers(out layerIDs, out layerNames);

        // Iterate through feature layers in the MapFunction (map resource) and set
        // attribute display parameters when editing attributes in the EditAttributesPanel.
        for (int i = 0; i < layerIDs.Length; i++)
        {
            string layerName = layerNames[i];
            int layerID = System.Int32.Parse(layerIDs[i]);
            if (layerName == "Parcels")
            {
                ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayInfo attributeDisplayInfo =
                    new ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayInfo(layerID,
                        ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayMode.ReadOnly);
                attributeDisplayInfo.Overrides.Add(
                    new ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayOverride("Parcel_ID",
                        ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayMode.Editable));
                EditorTask1.AttributeDisplay.AttributeDisplayInfos.Add(attributeDisplayInfo);
            }
            else if (layerName == "Road centerline")
            {
                ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayInfo attributeDisplayInfo =
                    new ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayInfo(layerID,
                        ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayMode.Editable);
                attributeDisplayInfo.Overrides.Add(
                    new ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayOverride("NAME",
                        ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayMode.ReadOnly));
                EditorTask1.AttributeDisplay.AttributeDisplayInfos.Add(attributeDisplayInfo);
            }
            else if (layerName == "Blocks")
            {
                ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayInfo attributeDisplayInfo =
                    new ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayInfo(layerID,
                        ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayMode.Hidden);
                attributeDisplayInfo.Overrides.Add(
                    new ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayOverride("Block",
                        ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayMode.Editable));
                EditorTask1.AttributeDisplay.AttributeDisplayInfos.Add(attributeDisplayInfo);
            }
        }
    }

    private void ReleaseContext()
    {
        // Loop through session variables and release any that are server contexts
        ESRI.ArcGIS.Server.IServerContext serverContext;
        for (int i = 0; i < Session.Count; i++)
        {
            // Attempt to get a reference to the current session variable as a server context
            serverContext = Session[i] as ESRI.ArcGIS.Server.IServerContext;
            if (serverContext != null)
            {
                // If the current session variable is a server context, release it.
                serverContext.RemoveAll();
                serverContext.ReleaseContext();
            }
        }

        // Clear session variables.  This will force creation of a new session if the user returns
        // to the page.  Otherwise, session variables may still be present and will cause errors.
        Session.RemoveAll();

        // Loop through the map resources referred to by MapResourceManager1 and explicitly dispose
        // any that are ArcGIS local map resources
        ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal mapResourceLocal;
        foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem mapResourceItem in
            MapResourceManager1.ResourceItems)
        {
            mapResourceLocal = mapResourceItem.Resource as
                ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal;
            if (mapResourceLocal != null)
                mapResourceLocal.Dispose();
        }
    }

    private bool HasNonPooledResources()
    {
        // Define a boolean and set it to false by default, indicating no non-pooled resources
        bool hasNonPooledResource = false;

        // Now go through all resources and find any non-pooled local resources
        ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal mapResourceLocal = null;
        ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.GISDataSourceLocal gisDataSourceLocal = null;

        // First, check the map resourceItems
        foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem mapResourceItem in MapResourceManager1.ResourceItems)
        {
            if (mapResourceItem != null)
            {
                // Get the local ArcGIS Server map resource underlying the current resource item
                mapResourceLocal = mapResourceItem.Resource as
                    ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal;

                if (mapResourceLocal != null)
                {
                    if (!MapResourceManager1.IsInitialized(mapResourceItem))
                        MapResourceManager1.Initialize(mapResourceItem);

                    // Get the local ArcGIS Server GIS data source from the local map resource
                    gisDataSourceLocal = mapResourceLocal.DataSource as
                        ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.GISDataSourceLocal;

                    // If the server object is not pooled, set the has non-pooled resource boolean to true
                    if (!gisDataSourceLocal.Connection.IsServerObjectPooled(
                    mapResourceLocal.ServerContextInfo.ServerObjectName, "MapServer"))
                        hasNonPooledResource = true;

                }
            }
        }
        return hasNonPooledResource;
    }

    #endregion

    protected void PostbackManager1_RequestReceived(object sender, PostbackManager_CSharp.AdfRequestEventArgs args)
    {
        // Parse the request arguments
        System.Collections.Specialized.NameValueCollection requestArgs =
            ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(args.RequestArguments);

        // Check the event argument and draw or clear graphics accordingly
        switch (requestArgs["EventArg"])
        {
            case "Dispose":
                if ((bool)Session["HasNonPooledResources"])
                    ReleaseContext();
                break;
        }
    }
}