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

Imports Microsoft.VisualBasic
Imports System
Public Partial Class _Default
  Inherits System.Web.UI.Page
  #Region "Instance Variable Declarations"

  Private m_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
        m_layerDataTable = New System.Data.DataTable("layerTable")
        Dim layerNameDataColumn As System.Data.DataColumn = New System.Data.DataColumn("layerName")
        Dim layerPathDataColumn As System.Data.DataColumn = New System.Data.DataColumn("layerPath")
        m_layerDataTable.Columns.Add(layerNameDataColumn)
        m_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 System.IO.StreamReader = 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 = m_layerDataTable.NewRow()
          dataRow(0) = layerSpecs(0)
          dataRow(1) = layerSpecs(1)
          m_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 = m_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_Data"
    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 ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection = 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 mapImage As ESRI.ArcGIS.Carto.IImageResult = mapServer.ExportMapImage(aoMapDescription, imageDescription)
        MapImageOutput.ImageUrl = mapImage.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