ArcGIS Routing with NAServer
ArcGIS_NAServer_Routing_CSharp\Default_Static.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.
// 



using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using ESRI.ArcGIS.ADF.ArcGISServer;

public partial class _Default : System.Web.UI.Page
{
  // Member Variables
  private const string SERVER_NAME = "localhost";
    //private const string ROUTE_SERVICE_NAME = "SanFrancisco";
    //private const string LOCATOR_SERVICE_NAME = "SanFranciscoLocator";

  protected void Page_Load(object sender, EventArgs e)
  {
    Page.Title = "Simple Routing Application";
  }
  protected void btnGetDirections_Click(object sender, EventArgs e)
  {
    Solve();
  }

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

    try
    {
      // Get the NAServer
            using (NAServerProxy naServer = new ESRI.ArcGIS.ADF.ArcGISServer.NAServerProxy("http://tasks.arcgisonline.com/ArcGIS/services/NetworkAnalysis/ESRI_Route_NA/MapServer/NAServer"))

      //using (NAServerProxy naServer = NAServerProxy.Create(SERVER_NAME, ROUTE_SERVICE_NAME, null))
      {
        if (naServer == null)
          throw (new System.Exception("Could not find the web service."));

        // Get the NAServerSolverParams
        string[] naLayers = naServer.GetNALayerNames(esriNAServerLayerType.esriNAServerRouteLayer);

        NAServerSolverParams solverParams = naServer.GetSolverParameters(naLayers[0]) as NAServerSolverParams;

        // Set the NAServerRouteParams
        NAServerRouteParams routeParams = solverParams as NAServerRouteParams;
        DateTime time;
        routeParams.UseStartTime = DateTime.TryParse(txtStartTime.Value, out time);
        if (routeParams.UseStartTime)
          routeParams.StartTime = time;

        routeParams.ReturnMap = chkShowMap.Checked; ;
        routeParams.ReturnRouteGeometries = false;
        routeParams.ReturnStops = false;
        routeParams.ReturnDirections = chkShowDirections.Checked;
                routeParams.DirectionsTimeAttributeName = "Time";// "Minutes";
                routeParams.ImpedanceAttributeName = "Time";// "Minutes";

        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
        NAServerSolverResults solverResults;
        solverResults = naServer.Solve(solverParams);

        // Display results
        OutputResults(solverResults);
      }
    }
    catch (Exception exception)
    {

      pnlDirectionSummary.Visible = false;
      lblDirections.Visible = false;
      lblTotalDistance.Visible = false;
      dataGridDirections.Visible = false;
      lblError.Text = "An error has occurred Mesage = " + exception.Message;
    }
  }

  /// <summary>
  /// This function shows how to populate stop locations using an array of PropertySets
  /// </summary>
  private void LoadLocations(NAServerSolverParams solverParams)
  {
    // Geocode Addresses
    PropertySet[] propSets = new PropertySet[2];
    propSets[0] = GeocodeAddress(txtFromStreet.Value, txtFromCity.Value, txtFromState.Value, txtFromZip.Value);
    propSets[1] = GeocodeAddress(txtToStreet.Value, txtToCity.Value, txtToState.Value, txtToZip.Value);

    NAServerPropertySets StopsPropSets = new NAServerPropertySets();
    StopsPropSets.PropertySets = propSets;

    NAServerRouteParams routeParams = solverParams as NAServerRouteParams;
    routeParams.Stops = StopsPropSets;
  }

  /// <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 PropertySet GeocodeAddress(string streetAddress, string city, string state, string zipCode)
  {
    PropertySet propSet = null;

    try
    {
            using (ESRI.ArcGIS.ADF.ArcGISServer.GeocodeServerProxy gc = new ESRI.ArcGIS.ADF.ArcGISServer.GeocodeServerProxy("http://tasks.arcgisonline.com/ArcGIS/services/Locators/TA_Address_NA/GeocodeServer")) 

      //using (GeocodeServerProxy gc = GeocodeServerProxy.Create(SERVER_NAME, LOCATOR_SERVICE_NAME, null))
      {
        PropertySet addressProperties = new PropertySet();

        Fields addressFields;
        Field field;

        PropertySetProperty[] propSetProperty = new PropertySetProperty[4];
        addressFields = gc.GetAddressFields();
        for (int i = 0; i < addressFields.FieldArray.GetLength(0); i++)
        {
          field = addressFields.FieldArray[i];

          if (field.Name.Equals("ADDRESS", StringComparison.OrdinalIgnoreCase))
            propSetProperty[0] = CreatePropertySetProperty(field.AliasName, streetAddress) as PropertySetProperty;

          if (field.Name.Equals("CITY", StringComparison.OrdinalIgnoreCase))
            propSetProperty[1] = CreatePropertySetProperty(field.AliasName, city) as PropertySetProperty;

          if (field.Name.Equals("STATE", StringComparison.OrdinalIgnoreCase))
            propSetProperty[2] = CreatePropertySetProperty(field.AliasName, state) as PropertySetProperty;

          if (field.Name.Equals("ZIP", StringComparison.OrdinalIgnoreCase) || field.Name.Equals("ZONE", StringComparison.OrdinalIgnoreCase))
            propSetProperty[3] = CreatePropertySetProperty(field.AliasName, zipCode) as PropertySetProperty;

        }

        addressProperties.PropertyArray = propSetProperty;

        // find the matching address  
        propSet = gc.GeocodeAddress(addressProperties, null);
      }
    }
    catch (Exception exception)
    {
      lblError.Text = "An error has occurred Mesage = " + exception.Message;
    }

    // Throw and error if the geocoded address is "Unmatched"
    if ((propSet != null) && (propSet.PropertyArray[1].Value.ToString() == "U"))
      throw (new System.Exception("Could not geocode [" + streetAddress + "]"));

    // Overwrite the "matched" property with the "Name" of the street
    propSet.PropertyArray[1].Key = "Name";
    propSet.PropertyArray[1].Value = streetAddress;

    return propSet;
  }

  /// <summary>
  /// CreatePropertySetProperty
  /// </summary> 
  private PropertySetProperty CreatePropertySetProperty(string key, object value)
  {
    PropertySetProperty propSetProperty = new PropertySetProperty();
    propSetProperty.Key = key;
    propSetProperty.Value = value;
    return propSetProperty;
  }

  /// <summary>
  /// Output Results map, Directions
  /// </summary>
  private void OutputResults(NAServerSolverResults solverResults)
  {
    string messagesSolverResults = "";

    // Output Solve messages
    GPMessages gpMessages = solverResults.SolveMessages;
    GPMessage[] arrGPMessage = gpMessages.GPMessages1;
    if (arrGPMessage != null)
    {
      for (int i = 0; i < arrGPMessage.GetLength(0); i++)
      {
        GPMessage gpMessage = arrGPMessage[i];
        messagesSolverResults += "\n" + gpMessage.MessageDesc;
      }
    }
    lblError.Text = messagesSolverResults;

    NAServerRouteResults RouteSolverResults = solverResults as NAServerRouteResults;
    // Display turn-by-turn directions
    if (chkShowDirections.Checked == true)
      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;
    }

    // Display the Map
    if (chkShowMap.Checked)
    {
      // 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;
    }
  }

  /// <summary>
  /// Output Directions if a dataGrid control
  /// </summary> 
  private void OutputDirections(NAStreetDirections[] serverDirections)
  {
    if (serverDirections == null)
      return;

    // get Directions from the ith route
    NAStreetDirections directions;
    directions = serverDirections[0];

    // get Summary (Total Distance and Time)
    NAStreetDirection direction = directions.Summary;
    string totallength = null, totaltime = null;
    string[] SummaryStrings = direction.Strings;
    for (int k = SummaryStrings.GetLowerBound(0); k < SummaryStrings.GetUpperBound(0); k++)
    {
      if (direction.StringTypes[k] == esriDirectionsStringType.esriDSTLength)
        totallength = SummaryStrings[k];
      if (direction.StringTypes[k] == esriDirectionsStringType.esriDSTTime)
        totaltime = SummaryStrings[k];
    }

    // Display the direction in a DataGrid
    DataSet dataSet = new DataSet("dataSet");
    DataTable dataTable = new DataTable("Results");
    dataSet.Tables.Add(dataTable);

    DataColumn dataColumn = null;
    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
    DataRow newDataRow;
    NAStreetDirection[] StreetDirections = directions.Directions;
    for (int directionIndex = StreetDirections.GetLowerBound(0); directionIndex <= StreetDirections.GetUpperBound(0); directionIndex++)
    {
      NAStreetDirection streetDirection = StreetDirections[directionIndex];
      string[] StringStreetDirection = streetDirection.Strings;
      newDataRow = dataTable.NewRow();
      newDataRow[0] = System.Convert.ToString(directionIndex + 1);

      for (int stringIndex = StringStreetDirection.GetLowerBound(0); stringIndex <= StringStreetDirection.GetUpperBound(0); stringIndex++)
      {
        if (streetDirection.StringTypes[stringIndex] == esriDirectionsStringType.esriDSTGeneral ||
          streetDirection.StringTypes[stringIndex] == esriDirectionsStringType.esriDSTDepart ||
          streetDirection.StringTypes[stringIndex] == esriDirectionsStringType.esriDSTArrive)
          newDataRow[1] = StringStreetDirection[stringIndex];

        if (streetDirection.StringTypes[stringIndex] == esriDirectionsStringType.esriDSTEstimatedArrivalTime)
          newDataRow[2] = StringStreetDirection[stringIndex];
      }

      dataTable.Rows.Add(newDataRow);
    }

    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;
  }
}