Server spatial query server object extension
SpatialQuerySOE.Manager_VBNet\Configurator.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.
' 

Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.Text

Namespace SpatialQuerySOE.Manager_VBNet
  ''' <summary>
  ''' SpatialQuerySOE property configuration page for Manager.  Defines the appearance and behavior of the page.
  ''' </summary>
  Public Class Configurator
    Implements ESRI.ArcGIS.ServerManager.IServerObjectExtensionConfigurator

#Region "Member variables"

    ' Controls to enable configuration of the SOE's layer and field
    Private m_layersDropDown As New System.Web.UI.WebControls.DropDownList()
    Private m_fieldsDropDown As New System.Web.UI.WebControls.DropDownList()

    ' The SOE's current layer
    Private m_layer As String

    ' The SOE's current field
    Private m_field As String

    ' JSON string storing the names of the current service's layers and their fields
    Private m_jsonServiceLayersAndFields As String = "{}"

#End Region

#Region "IServerObjectExtensionConfigurator Members"

#Region "Properties - HtmlElementIds, SupportingJavaScript"

    ''' <summary>
    ''' IDs of the controls that define SOE properties
    ''' </summary>
    'Public ReadOnly Property HtmlElementIds() As List(Of String)
    '  Get
    '    Return New List(Of String)(New String() {"layersDropDown", "fieldsDropDown"})
    '  End Get
    'End Property
    Public ReadOnly Property HtmlElementIds1() As System.Collections.Generic.List(Of String) Implements ESRI.ArcGIS.ServerManager.IServerObjectExtensionConfigurator.HtmlElementIds
      Get
        Return New List(Of String)(New String() {"layersDropDown", "fieldsDropDown"})
      End Get
    End Property

    ''' <summary>
    ''' JavaScript to execute when the property page is loaded
    ''' </summary>
    Public ReadOnly Property SupportingJavaScript() As String Implements ESRI.ArcGIS.ServerManager.IServerObjectExtensionConfigurator.SupportingJavaScript
      Get
        Return String.Format("" & ControlChars.CrLf & "                    // JSON object storing the names of the current service's layers and their fields" & ControlChars.CrLf & "                    var layerFieldsMapping = {0};" & ControlChars.CrLf & ControlChars.CrLf & "                    // ExtensionConfigurator is a global JavaScript object defined by Manager and available to SOE property page" & ControlChars.CrLf & "                    // implementations.  Here we use it to define the client logic to execute when a new layer is selected." & ControlChars.CrLf & "                    ExtensionConfigurator.OnLayerChanged = function(layersDropDown) {{" & ControlChars.CrLf & "                        // Get the currently selected layer                           " & ControlChars.CrLf & "                        var layerName = layersDropDown.options[layersDropDown.selectedIndex].value;" & ControlChars.CrLf & "                        // Get the fields drop down and the number of items in it" & ControlChars.CrLf & "                        var fieldsDropDown = document.getElementById('fieldsDropDown');  " & ControlChars.CrLf & "                        var len = fieldsDropDown.options ? fieldsDropDown.options.length : 0;" & ControlChars.CrLf & ControlChars.CrLf & "                        // Remove all the drop down's items" & ControlChars.CrLf & "                        for(var i=0; i < len; i++)" & ControlChars.CrLf & "                            fieldsDropDown.remove(0);" & ControlChars.CrLf & ControlChars.CrLf & "                        // Get the fields for the currently selected layer and populate the fields drop down with them" & ControlChars.CrLf & "                        var fieldsArray = layerFieldsMapping[layerName];" & ControlChars.CrLf & "                        if(fieldsArray)" & ControlChars.CrLf & "                        {{  " & ControlChars.CrLf & "                            for(i=0; i < fieldsArray.length; i++)" & ControlChars.CrLf & "                                fieldsDropDown.options.add(new Option(fieldsArray[i], fieldsArray[i]));" & ControlChars.CrLf & ControlChars.CrLf & "                            fieldsDropDown.options[0].selected = true;" & ControlChars.CrLf & "                        }}" & ControlChars.CrLf & "                    }}", m_jsonServiceLayersAndFields)
      End Get
    End Property

#End Region

#Region "Methods - LoadConfigurator, SaveProperties"

    ''' <summary>
    ''' Called when the property page is loaded
    ''' </summary>
    ''' <param name="serverContext">server context for the service</param>
    ''' <param name="ServerObjectProperties">properties of the server object (i.e. service)</param>
    ''' <param name="ExtensionProperties">SOE properties for the current server object</param>
    ''' <param name="InfoProperties">global SOE properties</param>
    ''' <param name="isEnabled">whether the SOE is enabled on the current server object</param>
    ''' <param name="servicesEndPoint">end point for server's web services </param>
    ''' <param name="serviceName">name of the server object</param>
    ''' <returns>An HTML string that defines the property page's UI</returns>
    Public Function LoadConfigurator(ByVal serverContext As ESRI.ArcGIS.Server.IServerContext, ByVal ServerObjectProperties As System.Collections.Specialized.NameValueCollection, ByVal ExtensionProperties As System.Collections.Specialized.NameValueCollection, ByVal InfoProperties As System.Collections.Specialized.NameValueCollection, ByVal isEnabled As Boolean, ByVal servicesEndPoint As String, ByVal serviceName As String) As String Implements ESRI.ArcGIS.ServerManager.IServerObjectExtensionConfigurator.LoadConfigurator
      ' Just return a message if the SOE is not enabled on the current service
      If (Not isEnabled) Then
        Return ("<span>No Properties to configure</span>")
      End If

      ' Initialize member variables holding the SOE's properties
      If (Not String.IsNullOrEmpty(ExtensionProperties("LayerName"))) Then
        m_layer = ExtensionProperties("LayerName")
      End If
      If (Not String.IsNullOrEmpty(ExtensionProperties("FieldName"))) Then
        m_field = ExtensionProperties("FieldName")
      End If


      'Container div and table          
      Dim propertiesDiv As New System.Web.UI.HtmlControls.HtmlGenericControl("propertiesDiv")
      propertiesDiv.Style(System.Web.UI.HtmlTextWriterStyle.Padding) = "10px"

      Dim table As New System.Web.UI.HtmlControls.HtmlTable()
      table.CellSpacing = 4
      table.CellPadding = table.CellSpacing
      propertiesDiv.Controls.Add(table)


      ' Header row
      Dim row As New System.Web.UI.HtmlControls.HtmlTableRow()
      table.Rows.Add(row)

      Dim cell As New System.Web.UI.HtmlControls.HtmlTableCell()
      row.Cells.Add(cell)
      cell.ColSpan = 2

      Dim lbl As New System.Web.UI.WebControls.Label()
      lbl.Text = "Choose the layer and field."
      cell.Controls.Add(lbl)


      ' Layer drop-down row
      row = New System.Web.UI.HtmlControls.HtmlTableRow()
      table.Rows.Add(row)

      cell = New System.Web.UI.HtmlControls.HtmlTableCell()
      row.Cells.Add(cell)

      lbl = New System.Web.UI.WebControls.Label()
      cell.Controls.Add(lbl)
      lbl.Text = "Layer:"

      cell = New System.Web.UI.HtmlControls.HtmlTableCell()
      row.Cells.Add(cell)
      cell.Controls.Add(m_layersDropDown)
      m_layersDropDown.ID = "layersDropDown"

      ' Wire the OnLayerChanged JavaScript function (defined in SupportingJavaScript) to fire when a new layer is selected
      m_layersDropDown.Attributes("onchange") = "ExtensionConfigurator.OnLayerChanged(this);"


      ' Fields drop-down row
      row = New System.Web.UI.HtmlControls.HtmlTableRow()
      table.Rows.Add(row)

      cell = New System.Web.UI.HtmlControls.HtmlTableCell()
      row.Cells.Add(cell)

      lbl = New System.Web.UI.WebControls.Label()
      cell.Controls.Add(lbl)
      lbl.Text = "Fields:"

      cell = New System.Web.UI.HtmlControls.HtmlTableCell()
      row.Cells.Add(cell)
      cell.Controls.Add(m_fieldsDropDown)
      m_fieldsDropDown.ID = "fieldsDropDown"



      ' Get the path of the underlying map document and use it to populate the properties drop-downs
      Dim fileName As String = ServerObjectProperties("FilePath")
      populateDropDowns(serverContext, fileName)


      ' Render and return the HTML for the container div
      Dim stringWriter As New System.IO.StringWriter()
      Dim htmlWriter As New System.Web.UI.HtmlTextWriter(stringWriter)
      propertiesDiv.RenderControl(htmlWriter)
      Dim html As String = stringWriter.ToString()
      stringWriter.Close()
      Return html
    End Function

    ''' <summary>
    ''' Persists the server object extension's properties
    ''' </summary>
    ''' <param name="serverContext">the server context of the service</param>
    ''' <param name="Request">values of the controls specified in HtmlElementIds</param>
    ''' <param name="isEnabled">whether the extension is enabled on the current server object</param>
    ''' <param name="ExtensionProperties">collection of server object properties to save</param>
    ''' <param name="InfoProperties">collection of global extension properties to save</param>
    Public Sub SaveProperties(ByVal serverContext As ESRI.ArcGIS.Server.IServerContext, ByVal Request As System.Collections.Specialized.NameValueCollection, ByVal isEnabled As Boolean, <System.Runtime.InteropServices.Out()> ByRef ExtensionProperties As System.Collections.Specialized.NameValueCollection, <System.Runtime.InteropServices.Out()> ByRef InfoProperties As System.Collections.Specialized.NameValueCollection) Implements ESRI.ArcGIS.ServerManager.IServerObjectExtensionConfigurator.SaveProperties
      ' Instantiate the properties collection and define the LayerName and FieldName properties
      ExtensionProperties = New System.Collections.Specialized.NameValueCollection()

      Dim layerName As String = Request("layersDropDown")
      If (Not String.IsNullOrEmpty(layerName)) Then
        ExtensionProperties.Add("LayerName", layerName)
      End If

      Dim fieldName As String = Request("fieldsDropDown")
      If (Not String.IsNullOrEmpty(fieldName)) Then
        ExtensionProperties.Add("FieldName", fieldName)
      End If

      InfoProperties = New System.Collections.Specialized.NameValueCollection()
    End Sub

#End Region

#End Region

    ' Retrieves the current service's layers and fields and populates the property page UI with them
    Private Sub populateDropDowns(ByVal serverContext As ESRI.ArcGIS.Server.IServerContext, ByVal mapDocPath As String)
      Dim mapDoc As ESRI.ArcGIS.Carto.IMapDocument = Nothing
      Dim map As ESRI.ArcGIS.Carto.IMap = Nothing
      Try
        ' Get the map underlying the current service
        mapDoc = CType(serverContext.CreateObject("esriCarto.MapDocument"), ESRI.ArcGIS.Carto.IMapDocument)
        mapDoc.Open(mapDocPath, Nothing)
        map = mapDoc.Map(0)

        ' Get IGeoFeatureLayers from the map
        Dim id As ESRI.ArcGIS.esriSystem.UID = CType(serverContext.CreateObject("esriSystem.UID"), ESRI.ArcGIS.esriSystem.UID)
        id.Value = "{E156D7E5-22AF-11D3-9F99-00C04F6BC78E}"
        Dim enumLayer As ESRI.ArcGIS.Carto.IEnumLayer = map.Layers(id, True)

        ' Loop through each layer and the fields for that layer.  For each simple polygon layer, add its name and 
        ' a list containing the names of all its fields to the dictionary.
        Dim featureLayer As ESRI.ArcGIS.Carto.IFeatureLayer = CType(enumLayer.Next(), ESRI.ArcGIS.Carto.IFeatureLayer)
        Dim layersAndFieldsDictionary As New Dictionary(Of String, List(Of String))()
        Dim addFields As Boolean = False
        Do While featureLayer IsNot Nothing
          Dim fieldsList As New List(Of String)()

          ' Check whether the current layer is a simple polygon layer
          If featureLayer.FeatureClass.ShapeType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolygon AndAlso featureLayer.FeatureClass.FeatureType = ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTSimple Then
            ' Add the layer to the layers drop-down
            m_layersDropDown.Items.Add(featureLayer.Name)

            ' Check whether the fields drop-down should be initialized with fields from the current loop layer
            If featureLayer.Name = m_layer OrElse (m_layer Is Nothing AndAlso m_layersDropDown.Items.Count = 1) Then
              addFields = True
            End If

            ' Add each field to the fields list
            Dim fields As ESRI.ArcGIS.Geodatabase.IFields = featureLayer.FeatureClass.Fields
            For i As Integer = 0 To fields.FieldCount - 1
              Dim field As ESRI.ArcGIS.Geodatabase.IField = fields.Field(i)
              fieldsList.Add(field.Name)

              ' If the current loop layer is the first, add its fields to the fields drop-down
              If addFields Then
                m_fieldsDropDown.Items.Add(field.Name)
              End If
            Next i

            addFields = False

            ' Add the layer name and its fields to the dictionary
            layersAndFieldsDictionary.Add(featureLayer.Name, fieldsList)
          End If

          featureLayer = CType(enumLayer.Next(), ESRI.ArcGIS.Carto.IFeatureLayer)
        Loop

        ' Serialize the dictionary containing the layer and field names to JSON
        Dim serializer As New System.Web.Script.Serialization.JavaScriptSerializer()
        m_jsonServiceLayersAndFields = serializer.Serialize(layersAndFieldsDictionary)

        ' If a layer is defined for the extension, select it in the layers drop-down.
        If m_layer IsNot Nothing Then
          m_layersDropDown.SelectedValue = m_layer
        End If

        ' If a field is defined for the extension, select it in the fields drop-down.
        If m_field IsNot Nothing Then
          m_fieldsDropDown.SelectedValue = m_field
        End If
      Catch
      Finally
        ' Close the service's map document
        If mapDoc IsNot Nothing Then
          mapDoc.Close()
        End If
        map = Nothing
      End Try
    End Sub

    
  End Class
End Namespace