ArcGIS Routing with NAServer
ArcGIS_NAServer_Routing_VBNet\Default_Static.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.
' 



Imports Microsoft.VisualBasic
Imports System
Imports System.Data
Imports System.Configuration
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Web.UI.HtmlControls
Imports ESRI.ArcGIS.ADF.ArcGISServer

Partial Public Class _Default
  Inherits System.Web.UI.Page
  ' Member Variables
  Private Const SERVER_NAME As String = "localhost"
    'Private Const ROUTE_SERVICE_NAME As String = "SanFrancisco"
    'Private Const LOCATOR_SERVICE_NAME As String = "SanFranciscoLocator"

  Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
    Page.Title = "Simple Routing Application"
  End Sub
  Protected Sub btnGetDirections_Click(ByVal sender As Object, ByVal e As EventArgs)
    Solve()
  End Sub

  ''' <summary>
  ''' This function
  '''     - sets the server and solver parameters
  '''     - populates the stops NALocations
  '''     - gets and displays the server results (map, directions)
  ''' </summary>
  Private Sub Solve()

    Try
      ' Get the NAServer
            'Using naServer As NAServerProxy = NAServerProxy.Create(SERVER_NAME, ROUTE_SERVICE_NAME, Nothing)
            Using naServer As NAServerProxy = New ESRI.ArcGIS.ADF.ArcGISServer.NAServerProxy("http://tasks.arcgisonline.com/ArcGIS/services/NetworkAnalysis/ESRI_Route_NA/MapServer/NAServer")


                If naServer Is Nothing Then
                    Throw (New System.Exception("Could not find the web service."))
                End If

                ' Get the NAServerSolverParams
                Dim naLayers As String() = naServer.GetNALayerNames(esriNAServerLayerType.esriNAServerRouteLayer)

                Dim solverParams As NAServerSolverParams = TryCast(naServer.GetSolverParameters(naLayers(0)), NAServerSolverParams)

                ' Set the NAServerRouteParams
                Dim routeParams As NAServerRouteParams = TryCast(solverParams, NAServerRouteParams)
                Dim time As DateTime
                routeParams.UseStartTime = DateTime.TryParse(txtStartTime.Value, time)
                If routeParams.UseStartTime Then
                    routeParams.StartTime = time
                End If

                routeParams.ReturnMap = chkShowMap.Checked

                routeParams.ReturnRouteGeometries = False
                routeParams.ReturnStops = False
                routeParams.ReturnDirections = chkShowDirections.Checked
                routeParams.DirectionsTimeAttributeName = "Time"
                routeParams.ImpedanceAttributeName = "Time"

                routeParams.ImageDescription.ImageDisplay.ImageHeight = System.Convert.ToInt32(mapImageControl.Height.Value)
                routeParams.ImageDescription.ImageDisplay.ImageWidth = System.Convert.ToInt32(mapImageControl.Width.Value)

                ' Geocode two addresses and create the stop network locations
                LoadLocations(solverParams)

                ' Solve the Route
                Dim solverResults As NAServerSolverResults
                solverResults = naServer.Solve(solverParams)

                ' Display results
                OutputResults(solverResults)
            End Using

        Catch exception As Exception

            pnlDirectionSummary.Visible = False
            lblDirections.Visible = False
            lblTotalDistance.Visible = False
            dataGridDirections.Visible = False
            lblError.Text = "An error has occurred Mesage = " & exception.Message
        End Try
  End Sub

  ''' <summary>
  ''' This function shows how to populate stop locations using an array of PropertySets
  ''' </summary>
  Private Sub LoadLocations(ByVal solverParams As NAServerSolverParams)
    ' Geocode Addresses
    Dim propSets As PropertySet() = New PropertySet(1) {}
    propSets(0) = GeocodeAddress(txtFromStreet.Value, txtFromCity.Value, txtFromState.Value, txtFromZip.Value)
    propSets(1) = GeocodeAddress(txtToStreet.Value, txtToCity.Value, txtToState.Value, txtToZip.Value)

    Dim StopsPropSets As NAServerPropertySets = New NAServerPropertySets()
    StopsPropSets.PropertySets = propSets

    Dim routeParams As NAServerRouteParams = TryCast(solverParams, NAServerRouteParams)
    routeParams.Stops = StopsPropSets
  End Sub

  ''' <summary>
  ''' Geocode an address based on the street name, city, state, and zip code
  ''' Throws and exception and returns null if the address was unmatched.
  ''' </summary> 
  Private Function GeocodeAddress(ByVal streetAddress As String, ByVal city As String, ByVal state As String, ByVal zipCode As String) As PropertySet
    Dim propSet As PropertySet = Nothing

    Try
            'Using gc As GeocodeServerProxy = GeocodeServerProxy.Create(SERVER_NAME, LOCATOR_SERVICE_NAME, Nothing)
            Using gc As GeocodeServerProxy = New ESRI.ArcGIS.ADF.ArcGISServer.GeocodeServerProxy("http://tasks.arcgisonline.com/ArcGIS/services/Locators/TA_Address_NA/GeocodeServer")
                Dim addressProperties As PropertySet = New PropertySet()

                Dim addressFields As Fields
                Dim field As Field

                Dim propSetProperty As PropertySetProperty() = New PropertySetProperty(3) {}
                addressFields = gc.GetAddressFields()
                Dim i As Integer = 0
                Do While i < addressFields.FieldArray.GetLength(0)
                    field = addressFields.FieldArray(i)

                    If field.Name.Equals("ADDRESS", StringComparison.OrdinalIgnoreCase) Then
                        propSetProperty(0) = TryCast(CreatePropertySetProperty(field.AliasName, streetAddress), PropertySetProperty)
                    End If

                    If field.Name.Equals("CITY", StringComparison.OrdinalIgnoreCase) Then
                        propSetProperty(1) = TryCast(CreatePropertySetProperty(field.AliasName, city), PropertySetProperty)
                    End If

                    If field.Name.Equals("STATE", StringComparison.OrdinalIgnoreCase) Then
                        propSetProperty(2) = TryCast(CreatePropertySetProperty(field.AliasName, state), PropertySetProperty)
                    End If

                    If field.Name.Equals("ZIP", StringComparison.OrdinalIgnoreCase) OrElse field.Name.Equals("ZONE", StringComparison.OrdinalIgnoreCase) Then
                        propSetProperty(3) = TryCast(CreatePropertySetProperty(field.AliasName, zipCode), PropertySetProperty)
                    End If

                    i += 1
                Loop

                addressProperties.PropertyArray = propSetProperty

                ' find the matching address  
                propSet = gc.GeocodeAddress(addressProperties, Nothing)
            End Using
        Catch exception As Exception
            lblError.Text = "An error has occurred Mesage = " & exception.Message
        End Try

    ' Throw and error if the geocoded address is "Unmatched"
    If (Not propSet Is Nothing) AndAlso (propSet.PropertyArray(1).Value.ToString() = "U") Then
      Throw (New System.Exception("Could not geocode [" & streetAddress & "]"))
    End If

    ' Overwrite the "matched" property with the "Name" of the street
    propSet.PropertyArray(1).Key = "Name"
    propSet.PropertyArray(1).Value = streetAddress

    Return propSet
  End Function

  ''' <summary>
  ''' CreatePropertySetProperty
  ''' </summary> 
  Private Function CreatePropertySetProperty(ByVal key As String, ByVal value As Object) As PropertySetProperty
    Dim propSetProperty As PropertySetProperty = New PropertySetProperty()
    propSetProperty.Key = key
    propSetProperty.Value = value
    Return propSetProperty
  End Function

  ''' <summary>
  ''' Output Results map, Directions
  ''' </summary>
  Private Sub OutputResults(ByVal solverResults As NAServerSolverResults)
    Dim messagesSolverResults As String = ""

    ' Output Solve messages
    Dim gpMessages As GPMessages = solverResults.SolveMessages
    Dim arrGPMessage As GPMessage() = gpMessages.GPMessages1
    If Not arrGPMessage Is Nothing Then
      Dim i As Integer = 0
      Do While i < arrGPMessage.GetLength(0)
        Dim gpMessage As GPMessage = arrGPMessage(i)
        messagesSolverResults &= Constants.vbLf + gpMessage.MessageDesc
        i += 1
      Loop
    End If
    lblError.Text = messagesSolverResults

    Dim RouteSolverResults As NAServerRouteResults = TryCast(solverResults, NAServerRouteResults)
    ' Display turn-by-turn directions
    If chkShowDirections.Checked = True Then
      OutputDirections(RouteSolverResults.Directions)
    Else
      ' Or simply display the total impedance for the route
      lblTotalTime.Text = "Total Time: " & RouteSolverResults.TotalImpedances(0).ToString("F") & " mn"
      lblTotalDistance.Visible = False
      pnlDirectionSummary.Visible = True
      lblDirections.Visible = False
      dataGridDirections.Visible = False
    End If

    ' Display the Map
    If chkShowMap.Checked Then
      ' Save the image to session state to be drawn by the DefaultMap page
      Session("MapImage") = System.Drawing.Image.FromStream(New System.IO.MemoryStream(RouteSolverResults.MapImage.ImageData))
      mapImageControl.Visible = True
    Else
      mapImageControl.Visible = False
    End If
  End Sub

  ''' <summary>
  ''' Output Directions if a dataGrid control
  ''' </summary> 
  Private Sub OutputDirections(ByVal serverDirections As NAStreetDirections())
    If serverDirections Is Nothing Then
      Return
    End If

    ' get Directions from the ith route
    Dim directions As NAStreetDirections
    directions = serverDirections(0)

    ' get Summary (Total Distance and Time)
    Dim direction As NAStreetDirection = directions.Summary
    Dim totallength As String = Nothing, totaltime As String = Nothing
    Dim SummaryStrings As String() = direction.Strings
    Dim k As Integer = SummaryStrings.GetLowerBound(0)
    Do While k < SummaryStrings.GetUpperBound(0)
      If direction.StringTypes(k) = esriDirectionsStringType.esriDSTLength Then
        totallength = SummaryStrings(k)
      End If
      If direction.StringTypes(k) = esriDirectionsStringType.esriDSTTime Then
        totaltime = SummaryStrings(k)
      End If
      k += 1
    Loop

    ' Display the direction in a DataGrid
    Dim dataSet As DataSet = New DataSet("dataSet")
    Dim dataTable As DataTable = New DataTable("Results")
    dataSet.Tables.Add(dataTable)

    Dim dataColumn As DataColumn = Nothing
    dataColumn = New DataColumn("Step ")
    dataTable.Columns.Add(dataColumn)
    dataColumn = New DataColumn("Directions ")
    dataTable.Columns.Add(dataColumn)
    dataColumn = New DataColumn("Estimated Arrival Time ")
    dataTable.Columns.Add(dataColumn)

    ' Then add a node for each step-by-step directions
    Dim newDataRow As DataRow
    Dim StreetDirections As NAStreetDirection() = directions.Directions
    Dim directionIndex As Integer = StreetDirections.GetLowerBound(0)
    Do While directionIndex <= StreetDirections.GetUpperBound(0)
      Dim streetDirection As NAStreetDirection = StreetDirections(directionIndex)
      Dim StringStreetDirection As String() = streetDirection.Strings
      newDataRow = dataTable.NewRow()
      newDataRow(0) = System.Convert.ToString(directionIndex + 1)

      Dim stringIndex As Integer = StringStreetDirection.GetLowerBound(0)
      Do While stringIndex <= StringStreetDirection.GetUpperBound(0)
        If streetDirection.StringTypes(stringIndex) = esriDirectionsStringType.esriDSTGeneral OrElse streetDirection.StringTypes(stringIndex) = esriDirectionsStringType.esriDSTDepart OrElse streetDirection.StringTypes(stringIndex) = esriDirectionsStringType.esriDSTArrive Then
          newDataRow(1) = StringStreetDirection(stringIndex)
        End If

        If streetDirection.StringTypes(stringIndex) = esriDirectionsStringType.esriDSTEstimatedArrivalTime Then
          newDataRow(2) = StringStreetDirection(stringIndex)
        End If
        stringIndex += 1
      Loop

      dataTable.Rows.Add(newDataRow)
      directionIndex += 1
    Loop

    dataGridDirections.DataSource = dataSet
    dataGridDirections.DataBind()
    dataGridDirections.Visible = True

    ' Display Total Distance and Total Time
    lblTotalDistance.Text = "Total Distance: " & totallength
    lblTotalTime.Text = "Total Time: " & totaltime
    pnlDirectionSummary.Visible = True
    lblDirections.Visible = True
    lblTotalDistance.Visible = True
  End Sub
End Class