ArcGIS Add dynamic data
ArcGIS_AddDynamicData_VBNet\Default.aspx.vb
' 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.
' 

' Illustrates how to add a new layer dynamically to a pooled ArcGIS Server map service and display the map image 
' using ArcObjects and ASP.NET only - no Web ADF controls
Partial Public Class _Default
    Inherits System.Web.UI.Page
#Region "Instance Variable Declarations"

    Private _layerDataTable As System.Data.DataTable

#End Region

#Region "ASP.NET Page Life Cycle Event Handlers"

    Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs)
        Try
            ' Read the contents of the layers.config file, which is assumed to contained the names and paths of the
            ' shapefiles that can be dynamically added to the map.  Store this data in a data table member variable.
            If (Not Page.IsPostBack) Then
                ' Create an empty data table to hold the shapefile names and paths
                _layerDataTable = New System.Data.DataTable("layerTable")
                Dim layerNameDataColumn As New System.Data.DataColumn("layerName")
                Dim layerPathDataColumn As New System.Data.DataColumn("layerPath")
                _layerDataTable.Columns.Add(layerNameDataColumn)
                _layerDataTable.Columns.Add(layerPathDataColumn)

                ' Get the root path of the web application and append the name of the file containing the
                ' shapefile list
                Dim rootPath As String = Server.MapPath("~")
                Dim layerCatalogPath As String = String.Format("{0}/layers.catalog", rootPath)

                ' Get a reader to access the layer catalog
                Dim layerCatalogReader As New System.IO.StreamReader(layerCatalogPath)

                ' Initialize the delimiter that separates shapefile names and paths in the layer catalog
                Dim layerDelimiterString As String = "="
                Dim layerDelimiter() As Char = layerDelimiterString.ToCharArray()

                ' Iterate through the lines of the layer catalog, adding each pair of shapefile names and paths
                ' to the data table
                Dim layerSpecs() As String = Nothing
                Dim currentLine As String = Nothing
                Do While layerCatalogReader.Peek() <> -1
                    currentLine = layerCatalogReader.ReadLine()

                    ' If the current line does not contain the delimiter, assume the end of the file has been reached
                    If (Not currentLine.Contains("=")) Then
                        Exit Do
                    End If

                    ' Split the current line into the shapefile name and path and add this data to the data table
                    layerSpecs = currentLine.Split(layerDelimiter)
                    Dim dataRow As System.Data.DataRow = _layerDataTable.NewRow()
                    dataRow(0) = layerSpecs(0)
                    dataRow(1) = layerSpecs(1)
                    _layerDataTable.Rows.Add(dataRow)
                Loop
                layerCatalogReader.Close()
            End If
        Catch exception As System.Exception
            ' Since the page has not yet rendered, we write the javascript to show an alert containing error info
            ' directly to the page response
            Dim jsErrorAlert As String = String.Format("<script>{0}</script>", Utility.GetJavaScriptErrorString(exception))
            Response.Write(jsErrorAlert)
        End Try
    End Sub

    Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs)
        Try
            ' Bind DropDownList to data table containing layer names
            DropDownList1.DataSource = _layerDataTable
            DropDownList1.DataTextField = "layerName"
            DropDownList1.DataValueField = "layerPath"
            DropDownList1.DataBind()

            If (Not Page.IsPostBack) Then
                If Session.IsNewSession Then
                    ' On initial page prerender, add session variables to track whether a layer was added and its id 
                    Session("dynamicLayerAdded") = False
                    Session("addedLayerID") = Nothing

                    ' Get the default map description from the server
                    Dim serverContext As ESRI.ArcGIS.Server.IServerContext = Me.GetServerContext()
                    Dim mapServer As ESRI.ArcGIS.Carto.IMapServer = TryCast(serverContext.ServerObject, ESRI.ArcGIS.Carto.IMapServer)
                    Dim mapServerInfo As ESRI.ArcGIS.Carto.IMapServerInfo = mapServer.GetServerInfo(mapServer.DefaultMapName)
                    Dim aoMapDescription As ESRI.ArcGIS.Carto.IMapDescription = mapServerInfo.DefaultMapDescription

                    ' Create a new map image and display in the page
                    CreateMapImage(serverContext, aoMapDescription)

                    serverContext.ReleaseContext()
                Else
                    ' If this is not the initial page prerender, then the map image must be recreated with the 
                    ' dynamically added layer, if one has been added.  So we create the server context, get the
                    ' map description that's holding layer visibility information from session, add the dynamic 
                    ' layer to the server state, create the map image based on server state, then remove the layer
                    ' from server state so it does not remain part of the map service
                    Dim serverContext As ESRI.ArcGIS.Server.IServerContext = GetServerContext()
                    Dim mapServer As ESRI.ArcGIS.Carto.IMapServer = TryCast(serverContext.ServerObject, ESRI.ArcGIS.Carto.IMapServer)
                    Dim mapServerInfo As ESRI.ArcGIS.Carto.IMapServerInfo = mapServer.GetServerInfo(mapServer.DefaultMapName)
                    Dim aoMapDescription As ESRI.ArcGIS.Carto.IMapDescription = mapServerInfo.DefaultMapDescription

                    If CBool(Session("dynamicLayerAdded")) Then
                        AddSelectedLayer(serverContext)
                    End If

                    CreateMapImage(serverContext, aoMapDescription)

                    RemoveDynamicLayer(serverContext)
                    serverContext.ReleaseContext()
                End If
            End If
        Catch exception As System.Exception
            ' Since the page has not yet rendered, we write the javascript to show an alert containing error info
            ' directly to the page response
            Dim jsErrorAlert As String = String.Format("<script>{0}</script>", Utility.GetJavaScriptErrorString(exception))
            Response.Write(jsErrorAlert)
        End Try
    End Sub

#End Region

#Region "ASP.NET Web Control Event Handlers"

    ' Fires when the Add Layer button is clicked
    Protected Sub AddLayer_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        Try
            ' Set the session variable indicating that a layer has been added during the current session
            Session("dynamicLayerAdded") = True

            ' Add the currently selected layer to the map service
            Dim serverContext As ESRI.ArcGIS.Server.IServerContext = GetServerContext()
            AddSelectedLayer(serverContext)

            ' Create a map image.  The image will contain the dynamic layer because that layer has been added
            ' to the map service, meaning the default map description will include this layer.
            Dim mapServer As ESRI.ArcGIS.Carto.IMapServer = CType(serverContext.ServerObject, ESRI.ArcGIS.Carto.IMapServer)
            Dim mapServerInfo As ESRI.ArcGIS.Carto.IMapServerInfo = mapServer.GetServerInfo(mapServer.DefaultMapName)
            Dim aoMapDescription As ESRI.ArcGIS.Carto.IMapDescription = mapServerInfo.DefaultMapDescription
            CreateMapImage(serverContext, aoMapDescription)

            ' Since we do not want to make a persistent change to the map service, we remove the layer once we
            ' have created an image containing it
            RemoveDynamicLayer(serverContext)

            serverContext.ReleaseContext()
        Catch exception As System.Exception
            ' Since the page is in a full page postback, we write the javascript to show an alert containing error info
            ' directly to the page response
            Dim jsErrorAlert As String = String.Format("<script>{0}</script>", Utility.GetJavaScriptErrorString(exception))
            Response.Write(jsErrorAlert)
        End Try
    End Sub

    ' Fires when the Change Extent button is clicked
    Protected Sub ChangeExtent_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        Try
            ' If a dynamic layer has been added during the current session, it needs to be re-added, since we
            ' are not persistently adding the layer to the service
            Dim serverContext As ESRI.ArcGIS.Server.IServerContext = Me.GetServerContext()

            If CBool(Session("dynamicLayerAdded")) Then
                AddSelectedLayer(serverContext)
            End If

            ' Get the map service's description and extent
            Dim mapServer As ESRI.ArcGIS.Carto.IMapServer = CType(serverContext.ServerObject, ESRI.ArcGIS.Carto.IMapServer)
            Dim mapServerInfo As ESRI.ArcGIS.Carto.IMapServerInfo = mapServer.GetServerInfo(mapServer.DefaultMapName)
            Dim mapDescription As ESRI.ArcGIS.Carto.IMapDescription = mapServerInfo.DefaultMapDescription

            Dim mapArea As ESRI.ArcGIS.Carto.IMapArea = mapDescription.MapArea
            Dim mapExtent As ESRI.ArcGIS.Carto.IMapExtent = TryCast(mapArea, ESRI.ArcGIS.Carto.IMapExtent)

            ' Create a new envelope and update the service extent with it
            Dim aoEnvelope As ESRI.ArcGIS.Geometry.IEnvelope = CType(serverContext.CreateObject("esriGeometry.Envelope"), ESRI.ArcGIS.Geometry.IEnvelope)
            aoEnvelope.PutCoords(-120, 30, -50, 50)
            mapExtent.Extent = aoEnvelope

            ' Create a map image  
            CreateMapImage(serverContext, mapDescription)

            ' Since we do not want to make a persistent change to the map service, we remove the layer once we
            ' have created the map image containing it
            RemoveDynamicLayer(serverContext)

            serverContext.ReleaseContext()
        Catch exception As System.Exception
            ' Since the page has not yet rendered, we write the javascript to show an alert containing error info
            ' directly to the page response
            Dim jsErrorAlert As String = String.Format("<script>{0}</script>", Utility.GetJavaScriptErrorString(exception))
            Response.Write(jsErrorAlert)
        End Try
    End Sub

#End Region

#Region "Instance Methods"

    ' Retrieves the server context of the map service specified by the serverName and mapServiceName variables
    Private Function GetServerContext() As ESRI.ArcGIS.Server.IServerContext
        Dim serverName As String = "localhost"
        Dim mapServiceName As String = "USA"
        Dim serverObjectManager As ESRI.ArcGIS.Server.IServerObjectManager

        ' Check whether the session variable storing the ServerObjectManager is null and initialize it if so.  
        ' This code only executes once because we only want to create one connection per session.
        If Session("SOM") Is Nothing Then
            ' Using ADF connection library
            Dim agsServerConnection As New ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection()
            agsServerConnection.Host = serverName
            agsServerConnection.Connect()

            serverObjectManager = agsServerConnection.ServerObjectManager
            Session("SOM") = serverObjectManager
        Else
            serverObjectManager = TryCast(Session("SOM"), ESRI.ArcGIS.Server.IServerObjectManager)
        End If

        ' Create a map server context with the specified map service name
        Dim serverContext As ESRI.ArcGIS.Server.IServerContext = serverObjectManager.CreateServerContext(mapServiceName, "MapServer")

        Return serverContext
    End Function

    ' Adds the currently selected layer to the map service
    Private Sub AddSelectedLayer(ByVal serverContext As ESRI.ArcGIS.Server.IServerContext)
        ' Use ArcObjects to get the ArcObjects map underlying the map service
        Dim mapServer As ESRI.ArcGIS.Carto.IMapServer = CType(serverContext.ServerObject, ESRI.ArcGIS.Carto.IMapServer)
        Dim mapServerObjects As ESRI.ArcGIS.Carto.IMapServerObjects2 = CType(mapServer, ESRI.ArcGIS.Carto.IMapServerObjects2)
        Dim mapName As String = mapServer.DefaultMapName
        Dim aoMap As ESRI.ArcGIS.Carto.IMap = mapServerObjects.Map(mapName)

        ' Retrieve the currently selected item and parse its value into the shapefile directory path and file name
        Dim listItem As System.Web.UI.WebControls.ListItem = DropDownList1.SelectedItem
        Dim lastSlashIndex As Integer = listItem.Value.LastIndexOf("/")
        Dim filePath As String = listItem.Value.Substring(0, lastSlashIndex)
        Dim fileName As String = listItem.Value.Substring(lastSlashIndex + 1)

        ' Get a reference to the shapefile directory as an ArcObjects FeatureWorkspace
        Dim workspaceFactory As ESRI.ArcGIS.Geodatabase.IWorkspaceFactory = CType(serverContext.CreateObject("esriDataSourcesFile.ShapefileWorkspaceFactory"), ESRI.ArcGIS.Geodatabase.IWorkspaceFactory)
        Dim workspace As ESRI.ArcGIS.Geodatabase.IWorkspace = workspaceFactory.OpenFromFile(filePath, 0)
        Dim featureWorkspace As ESRI.ArcGIS.Geodatabase.IFeatureWorkspace = CType(workspace, ESRI.ArcGIS.Geodatabase.IFeatureWorkspace)

        ' Get a reference to the shapefile as a GeoFeatureLayer
        Dim aoFeatureLayer As ESRI.ArcGIS.Carto.IFeatureLayer = CType(serverContext.CreateObject("esriCarto.FeatureLayer"), ESRI.ArcGIS.Carto.IFeatureLayer)
        ' Or use the guid for esriCarto.FeatureLayer
        'IFeatureLayer layer = (IFeatureLayer)in_mapcontext.CreateObject("{E663A651-8AAD-11D0-BEC7-00805F7C4268}");
        aoFeatureLayer.FeatureClass = featureWorkspace.OpenFeatureClass(fileName)
        aoFeatureLayer.Name = listItem.Text
        Dim geoFeatureLayer As ESRI.ArcGIS.Carto.IGeoFeatureLayer = CType(aoFeatureLayer, ESRI.ArcGIS.Carto.IGeoFeatureLayer)

        ' Create an ArcObjects color object with the color set to blue for use by the layer's renderer
        Dim rgbColor As ESRI.ArcGIS.Display.IRgbColor = CType(serverContext.CreateObject("esriDisplay.RgbColor"), ESRI.ArcGIS.Display.IRgbColor)
        rgbColor.Red = 0
        rgbColor.Green = 0
        rgbColor.Blue = 210

        ' Set the symbol of the GeoFeatureLayer's renderer to use the color initialized above
        Dim aoSimpleRenderer As ESRI.ArcGIS.Carto.ISimpleRenderer = CType(geoFeatureLayer.Renderer, ESRI.ArcGIS.Carto.ISimpleRenderer)
        Dim geometryType As ESRI.ArcGIS.Geometry.esriGeometryType = aoFeatureLayer.FeatureClass.ShapeType
        If geometryType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint Then
            Dim simpleMarkerSymbol As ESRI.ArcGIS.Display.ISimpleMarkerSymbol = CType(aoSimpleRenderer.Symbol, ESRI.ArcGIS.Display.ISimpleMarkerSymbol)
            simpleMarkerSymbol.Color = CType(rgbColor, ESRI.ArcGIS.Display.IColor)
        ElseIf geometryType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline Then
            Dim simpleLineSymbol As ESRI.ArcGIS.Display.ISimpleLineSymbol = CType(aoSimpleRenderer.Symbol, ESRI.ArcGIS.Display.ISimpleLineSymbol)
            simpleLineSymbol.Color = CType(rgbColor, ESRI.ArcGIS.Display.IColor)
        ElseIf geometryType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolygon Then
            Dim simpleFillSymbol As ESRI.ArcGIS.Display.ISimpleFillSymbol = CType(aoSimpleRenderer.Symbol, ESRI.ArcGIS.Display.ISimpleFillSymbol)
            simpleFillSymbol.Color = CType(rgbColor, ESRI.ArcGIS.Display.IColor)
        Else
            Throw New System.Exception("No renderer or symbol selected.  Shape type undetermined.")
        End If

        ' Add the layer to the map service's map
        aoMap.AddLayer(aoFeatureLayer)
        mapServerObjects.RefreshServerObjects()

        ' Store the map service ID of the layer in session
        Session("addedLayerID") = mapServerObjects.LayerID(mapName, aoFeatureLayer)
    End Sub

    ' Creates a JPEG image based on the passed-in server context and map description and sets the MapImage web 
    ' control to display it
    Private Sub CreateMapImage(ByVal serverContext As ESRI.ArcGIS.Server.IServerContext, ByVal aoMapDescription As ESRI.ArcGIS.Carto.IMapDescription)
        Dim imageType As ESRI.ArcGIS.Carto.IImageType
        Dim imageDescription As ESRI.ArcGIS.Carto.IImageDescription
        Dim imageDisplay As ESRI.ArcGIS.Carto.IImageDisplay

        imageType = TryCast(serverContext.CreateObject("esriCarto.ImageType"), ESRI.ArcGIS.Carto.IImageType)
        imageDescription = TryCast(serverContext.CreateObject("esriCarto.ImageDescription"), ESRI.ArcGIS.Carto.ImageDescription)
        imageDisplay = TryCast(serverContext.CreateObject("esriCarto.ImageDisplay"), ESRI.ArcGIS.Carto.ImageDisplay)

        ' Set properties to have the image output a JPEG and refer to it via URL
        imageType.Format = ESRI.ArcGIS.Carto.esriImageFormat.esriImageJPG
        imageType.ReturnType = ESRI.ArcGIS.Carto.esriImageReturnType.esriImageReturnURL

        ' Initialize image height and width based on the dimensions of the MapImage Image control
        imageDisplay.Height = CInt(Fix(MapImageOutput.Height.Value))
        imageDisplay.Width = CInt(Fix(MapImageOutput.Width.Value))
        imageDisplay.DeviceResolution = 96

        imageDescription.Display = imageDisplay
        imageDescription.Type = imageType

        Dim mapServer As ESRI.ArcGIS.Carto.IMapServer = CType(serverContext.ServerObject, ESRI.ArcGIS.Carto.IMapServer)

        ' Create the map image and set the MapImage control to display it
        Dim mapImageout As ESRI.ArcGIS.Carto.IImageResult = mapServer.ExportMapImage(aoMapDescription, imageDescription)
        MapImageOutput.ImageUrl = mapImageout.URL
        MapImageOutput.Visible = True
    End Sub

    ' Removes the dynamically added layer from the map service
    Private Sub RemoveDynamicLayer(ByVal serverContext As ESRI.ArcGIS.Server.IServerContext)
        ' Check whether a dynamic layer has been added during the session
        Dim layerAdded As Boolean = CBool(Session("dynamicLayerAdded"))

        If layerAdded Then
            ' Retrieve the dynamic layer from the map service and delete it.  Note that we know the layer has been
            ' added at index 0, so we can safely delete the layer at this index.
            Dim mapServer As ESRI.ArcGIS.Carto.IMapServer = CType(serverContext.ServerObject, ESRI.ArcGIS.Carto.IMapServer)
            Dim mapServerObjects As ESRI.ArcGIS.Carto.IMapServerObjects = CType(mapServer, ESRI.ArcGIS.Carto.IMapServerObjects)
            Dim aoMap As ESRI.ArcGIS.Carto.IMap = mapServerObjects.Map(mapServer.DefaultMapName)
            Dim aoLayer As ESRI.ArcGIS.Carto.ILayer = aoMap.Layer(0)

            aoMap.DeleteLayer(aoLayer)
            mapServerObjects.RefreshServerObjects()
        End If
    End Sub

#End Region
End Class