ArcGIS_Geocode_Search_VBNet\App_Code\SchoolDistrictLocatorService.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 <System.Web.Services.WebService(Namespace := "http://localhost/ArcGIS_SchoolDistrictGeocode_WebService/"), System.Web.Services.WebServiceBinding(ConformsTo := System.Web.Services.WsiProfiles.BasicProfile1_1)> _ Public Class SchoolDistrictLocatorService Inherits System.Web.Services.WebService Public Sub New() End Sub <System.Web.Services.WebMethod(Description:="Locates SchoolDistrict within the specified distance of the input address." & "Output is returned in an array. To see an example, input '1575 Apple Ln', '48304', '10000.'" & "Note that this method implements its functionality using ArcObjects.")> _ Public Function FindSchoolDistrictLocationsArcObjects(ByVal FullAddress As String, ByVal Distance As String) As SchoolDistrict() ' Make sure all inputs were specified If FullAddress Is Nothing OrElse String.IsNullOrEmpty(Distance.ToString) OrElse CDbl(Distance) = 0.0 Then Return Nothing End If ' Declare server context variables Dim mapServerContext As ESRI.ArcGIS.Server.IServerContext = Nothing Dim geocodeServerContext As ESRI.ArcGIS.Server.IServerContext = Nothing Dim geometryServerContext As ESRI.ArcGIS.Server.IServerContext = Nothing Try ' Connect to ArcGIS Server Dim adfIdentity As New ESRI.ArcGIS.ADF.Identity("username", "password", "domainOrmachine") Dim agsServerConnection As New ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection("localhost", adfIdentity) agsServerConnection.Connect() ' Get a reference to the server object manager to use in creating server objects Dim serverObjectManager As ESRI.ArcGIS.Server.IServerObjectManager = agsServerConnection.ServerObjectManager ' #Region "Geocode the input address" ' Create a server context for and get a reference to the RoadCenterline_Locator geocode service geocodeServerContext = serverObjectManager.CreateServerContext("RoadCenterline_Locator", "GeocodeServer") Dim geocodeServer As ESRI.ArcGIS.Location.IGeocodeServer = TryCast(geocodeServerContext.ServerObject, ESRI.ArcGIS.Location.IGeocodeServer) ' Instantate and populate a property set holding geocode operation input parameters Dim aoInputPropertySet As ESRI.ArcGIS.esriSystem.IPropertySet = TryCast(geocodeServerContext.CreateObject("esriSystem.PropertySet"), ESRI.ArcGIS.esriSystem.IPropertySet) aoInputPropertySet.SetProperty("Single Line Input", FullAddress) ' Execute the geocoding operation Dim aoResultsPropertySet As ESRI.ArcGIS.esriSystem.IPropertySet = geocodeServer.GeocodeAddress(aoInputPropertySet, Nothing) ' Retrieve the geocoded point from the operation results Dim aoLocationPoint As ESRI.ArcGIS.Geometry.IPoint = TryCast(aoResultsPropertySet.GetProperty("Shape"), ESRI.ArcGIS.Geometry.IPoint) ' #End Region ' #Region "Buffer the geocoded point" ' Create a server context for and get a reference to the geometry service. We will use this ' to execute buffer and project operations. geometryServerContext = serverObjectManager.CreateServerContext("Geometry", "GeometryServer") ' The point generated by the geocode operation is in the geocode server object's server context. ' It will be used in a geometry service operation, thus it must be available in the geometry ' server objects's server context. SaveObject serializes the ArcObjects point to a string. ' LoadObject deserializes the string to create an object in server context. Dim aoLocationPointInGeometryServer As ESRI.ArcGIS.Geometry.IPoint = CType(geometryServerContext.LoadObject(geocodeServerContext.SaveObject(aoLocationPoint)), ESRI.ArcGIS.Geometry.IPoint) Dim geometryServer As ESRI.ArcGIS.Geometry.IGeometryServer = TryCast(geometryServerContext.ServerObject, ESRI.ArcGIS.Geometry.IGeometryServer) ' Create a spatial reference in which to execute the buffer operation. This spatial ' reference's projection is optimized to minimize distortion in the vicinity of the ' operation. Dim aoBufferSpatialReference As ESRI.ArcGIS.Geometry.ISpatialReference = Utility.CreateOperationSpatialReference(aoLocationPointInGeometryServer, geometryServerContext) ' Store output spatial reference for use in the buffer operation. Also use to assign spatial reference ' to buffer generated by operation. Dim outputSpatialReference As ESRI.ArcGIS.Geometry.ISpatialReference = aoLocationPointInGeometryServer.SpatialReference ' Create a server context for and get a reference to the BloomfieldTownship map service. We will ' use this to access map information and query features. mapServerContext = serverObjectManager.CreateServerContext("BloomfieldTownship", "MapServer") Dim mapServer As ESRI.ArcGIS.Carto.IMapServer2 = TryCast(mapServerContext.ServerObject, ESRI.ArcGIS.Carto.IMapServer2) ' Get a reference to the map service's server info object Dim mapServerInfo As ESRI.ArcGIS.Carto.IMapServerInfo = mapServer.GetServerInfo(mapServer.DefaultMapName) ' Create a spatial reference environemnt for use by the ConvertUnitType method Dim spatialReferenceEnvironment As ESRI.ArcGIS.Geometry.SpatialReferenceEnvironment = TryCast(geometryServerContext.CreateObject("esriGeometry.SpatialReferenceEnvironment"), ESRI.ArcGIS.Geometry.SpatialReferenceEnvironment) ' Convert the map service's units to the type required by the buffer operation Dim bufferUnit As ESRI.ArcGIS.Geometry.IUnit = Utility.ConvertUnitType(mapServerInfo.MapUnits, spatialReferenceEnvironment) ' Package the geocoded point and buffer distance in arrays to pass to the buffer ' operation Dim aoInputGeometryArray As ESRI.ArcGIS.Geometry.IGeometryArray = TryCast(geometryServerContext.CreateObject("esriGeometry.GeometryArray"), ESRI.ArcGIS.Geometry.IGeometryArray) aoInputGeometryArray.Add(aoLocationPointInGeometryServer) Dim distancesArray As ESRI.ArcGIS.esriSystem.IDoubleArray = TryCast(geometryServerContext.CreateObject("esriSystem.DoubleArray"), ESRI.ArcGIS.esriSystem.IDoubleArray) distancesArray.Add(CDbl(Distance)) ' Execute the buffer operation Dim aoBufferGeometryArray As ESRI.ArcGIS.Geometry.IGeometryArray = geometryServer.Buffer(aoLocationPointInGeometryServer.SpatialReference, aoBufferSpatialReference, outputSpatialReference, distancesArray, bufferUnit, False, aoInputGeometryArray) ' Retrieve the buffer geometry from the operation results Dim aoBuffer As ESRI.ArcGIS.Geometry.IPolygon = TryCast(aoBufferGeometryArray.Element(0), ESRI.ArcGIS.Geometry.IPolygon) ' Assign output spatial reference to buffer geometry aoBuffer.SpatialReference = outputSpatialReference ' The polygon generated by the buffer operation is in the geometry server object's server context. ' It will be used in a query operation against a map service, thus it must be available in the map ' server objects server context. SaveObject serializes the ArcObjects polygon to a string. ' LoadObject deserializes the string to create an object in server context. Dim aoBufferInMapServer As ESRI.ArcGIS.Geometry.IPolygon = CType(mapServerContext.LoadObject(geometryServerContext.SaveObject(aoBuffer)), ESRI.ArcGIS.Geometry.IPolygon) ' #End Region ' #Region "Find SchoolDistrict sites within the buffer" ' Retrieve the map service's MapLayerInfos object to use in accessing information about ' the service's layers Dim mapLayerInfos As ESRI.ArcGIS.Carto.IMapLayerInfos = mapServerInfo.MapLayerInfos ' Retrieve the layer ID and geometry field name of the SchoolDistrict sites layer. This is the layer ' we will query to find SchoolDistrict sites within the buffer. Dim SchoolDistrictsLayerID As Integer = -1 Dim geometryFieldName As String = Nothing Dim i As Integer = 0 Do While i < mapLayerInfos.Count Dim mapLayerInfo As ESRI.ArcGIS.Carto.IMapLayerInfo = mapLayerInfos.Element(i) If mapLayerInfo.Name = "SchoolTaxDistrict" Then SchoolDistrictsLayerID = mapLayerInfo.ID Dim j As Integer = 0 Do While j < mapLayerInfo.Fields.FieldCount Dim field As ESRI.ArcGIS.Geodatabase.IField = mapLayerInfo.Fields.Field(j) If field.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGeometry Then geometryFieldName = field.Name Exit Do End If j += 1 Loop Exit Do End If i += 1 Loop ' Instantiate and initialize a spatial filter with the buffer geometry and SchoolDistrict sites ' layer geometry field name Dim aoSpatialFilter As ESRI.ArcGIS.Geodatabase.ISpatialFilter = TryCast(mapServerContext.CreateObject("esriGeodatabase.SpatialFilter"), ESRI.ArcGIS.Geodatabase.ISpatialFilter) aoSpatialFilter.Geometry = aoBufferInMapServer aoSpatialFilter.SpatialRel = ESRI.ArcGIS.Geodatabase.esriSpatialRelEnum.esriSpatialRelIntersects aoSpatialFilter.GeometryField = geometryFieldName ' Execute the query Dim aoRecordSet As ESRI.ArcGIS.Geodatabase.IRecordSet = mapServer.QueryFeatureData(mapServer.DefaultMapName, SchoolDistrictsLayerID, aoSpatialFilter) ' #End Region ' #Region "Package function output based on SchoolDistrict site data" ' Retrieve the School Description type fields Dim schoolDscrpIndex As Integer = -1 Dim currentIndex As Integer = 0 i = 0 Do While i < aoRecordSet.Fields.FieldCount Dim field As ESRI.ArcGIS.Geodatabase.IField = aoRecordSet.Fields.Field(i) If field.Name.ToUpper() = "SCHLDSCRP" Then schoolDscrpIndex = currentIndex Exit Do End If currentIndex += 1 i += 1 Loop Dim SchoolDistrictsList As New System.Collections.ArrayList() Dim SchoolDistrict As SchoolDistrict = Nothing ' Get a cursor to loop through the rows corresponding to SchoolDistrict site results Dim SchoolDistrictCursor As ESRI.ArcGIS.Geodatabase.ICursor = aoRecordSet.Cursor(False) Dim SchoolDistrictRow As ESRI.ArcGIS.Geodatabase.IRow = SchoolDistrictCursor.NextRow() ' For each SchoolDistrict site record, instantiate a new SchoolDistrict object and add it to the SchoolDistrict sites ' list object Do While SchoolDistrictRow IsNot Nothing SchoolDistrict = New SchoolDistrict(CStr(SchoolDistrictRow.Value(schoolDscrpIndex))) SchoolDistrictsList.Add(SchoolDistrict) SchoolDistrictRow = SchoolDistrictCursor.NextRow() Loop ' Copy the SchoolDistrict sites list to an array to be returned as the function result Dim SchoolDistrictsArray(SchoolDistrictsList.Count - 1) As SchoolDistrict SchoolDistrictsList.CopyTo(SchoolDistrictsArray) ' #End Region Return SchoolDistrictsArray Catch exception As System.Exception System.Diagnostics.Debug.WriteLine("Exception: " & exception.Message) Finally ' Make sure server contexts are released If mapServerContext IsNot Nothing Then mapServerContext.ReleaseContext() End If If geocodeServerContext IsNot Nothing Then geocodeServerContext.ReleaseContext() End If If geometryServerContext IsNot Nothing Then geometryServerContext.ReleaseContext() End If End Try Return Nothing End Function <System.Web.Services.WebMethod(Description:="Locates SchoolDistrict within the specified distance of the input address." & "Output is returned in an array. To see an example, input '1575 Apple ln', '10000.'" & "Note that this method implements its functionality using the ArcGIS Server SOAP API.")> _ Public Function FindSchoolDistrictLocationsSoap(ByVal FullAddress As String, ByVal Distance As String) As SchoolDistrict() ' Check to make sure all inputs are specified If FullAddress Is Nothing OrElse String.IsNullOrEmpty(Distance.ToString) OrElse CDbl(Distance) = 0.0 Then Return Nothing End If ' Declare server context variables Dim mapServerContext As ESRI.ArcGIS.Server.IServerContext = Nothing Dim geocodeServerContext As ESRI.ArcGIS.Server.IServerContext = Nothing Dim geometryServerContext As ESRI.ArcGIS.Server.IServerContext = Nothing Try ' Open a connection to ArcGIS Server Dim adfIdentity As New ESRI.ArcGIS.ADF.Identity("username", "password", "domainOrmachine") Dim agsServerConnection As New ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection("localhost", adfIdentity) agsServerConnection.Connect() ' Get a reference to the server object manager to use in creating server objects Dim serverObjectManager As ESRI.ArcGIS.Server.IServerObjectManager = agsServerConnection.ServerObjectManager ' #Region "Geocode the input address" ' Create an ArcGIS Server SOAP property set to hold the input to the geocode oparation Dim agsSoapInputPropertySet As New ESRI.ArcGIS.ADF.ArcGISServer.PropertySet() agsSoapInputPropertySet.PropertyArray = New ESRI.ArcGIS.ADF.ArcGISServer.PropertySetProperty(0) {} ' Specify the street property Dim agsSoapInputProperty As New ESRI.ArcGIS.ADF.ArcGISServer.PropertySetProperty() agsSoapInputProperty.Key = "Single Line Input" agsSoapInputProperty.Value = FullAddress agsSoapInputPropertySet.PropertyArray(0) = agsSoapInputProperty ' Create server context for the RoadCenterline_Locator geocoding service. We will use this to geocode ' the passed-in address. geocodeServerContext = serverObjectManager.CreateServerContext("RoadCenterline_Locator", "GeocodeServer") ' Get a reference to the geocoding service Dim geocodeServerDcomProxy As New ESRI.ArcGIS.ADF.ArcGISServer.GeocodeServerDcomProxy(geocodeServerContext, True) ' Execute the geocoding operation Dim agsSoapResultsPropertySet As ESRI.ArcGIS.ADF.ArcGISServer.PropertySet = geocodeServerDcomProxy.GeocodeAddress(agsSoapInputPropertySet, Nothing) ' Retrieve the geocoded point from the results array Dim agsSoapLocationPoint As ESRI.ArcGIS.ADF.ArcGISServer.PointN = Nothing For i As Integer = 0 To agsSoapResultsPropertySet.PropertyArray.Length - 1 If agsSoapResultsPropertySet.PropertyArray(i).Key = "Shape" Then agsSoapLocationPoint = TryCast(agsSoapResultsPropertySet.PropertyArray(i).Value, ESRI.ArcGIS.ADF.ArcGISServer.PointN) End If Next i ' #End Region ' #Region "Buffer the geocoded point" ' Create server context for the BloomfieldTownship map service. We will use this to access ' information about and query the map service mapServerContext = serverObjectManager.CreateServerContext("BloomfieldTownship", "MapServer") ' Get references to the map service and the service's server info Dim mapServerDcomProxy As New ESRI.ArcGIS.ADF.ArcGISServer.MapServerDcomProxy(mapServerContext, True) Dim mapServerInfo As ESRI.ArcGIS.ADF.ArcGISServer.MapServerInfo = mapServerDcomProxy.GetServerInfo(mapServerDcomProxy.GetDefaultMapName()) ' Convert the service's units into the type required for the buffer operation Dim bufferDistanceUnits As ESRI.ArcGIS.ADF.ArcGISServer.LinearUnit = Utility.ConvertUnitType(mapServerInfo.Units) ' Create server context for and get a reference to the geometry service. We will use this ' for buffer and project operations. geometryServerContext = serverObjectManager.CreateServerContext("Geometry", "GeometryServer") Dim geometryServerDcomProxy As New ESRI.ArcGIS.ADF.ArcGISServer.GeometryServerDcomProxy(geometryServerContext, True) ' Create a spatial reference in which to execute the buffer operation. This spatial ' reference's projection is optimized to minimize distortion in the vicinity of the ' operation. Dim agsSoapSpatialReference As ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference = Utility.CreateOperationSpatialReference(agsSoapLocationPoint, geometryServerDcomProxy) ' Package the geocoded point and buffer distance in arrays for passing to the buffer ' operation Dim agsSoapInputGeometryArray(0) As ESRI.ArcGIS.ADF.ArcGISServer.Geometry agsSoapInputGeometryArray(0) = agsSoapLocationPoint Dim distancesArray(0) As Double distancesArray(0) = CDbl(Distance) ' Output spatial reference for the buffer operation Dim outputSpatialReference As ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference = agsSoapLocationPoint.SpatialReference ' Execute the buffer operation Dim agsSoapBufferGeometryArray() As ESRI.ArcGIS.ADF.ArcGISServer.Geometry = geometryServerDcomProxy.Buffer(agsSoapLocationPoint.SpatialReference, agsSoapSpatialReference, outputSpatialReference, distancesArray, bufferDistanceUnits, False, agsSoapInputGeometryArray) ' #End Region ' #Region "Find SchoolDistrict sites within the buffer" ' Retrieve the layer ID and geometry field name of the SchoolDistrict sites layer. This is the layer ' we will query to find SchoolDistrict sites within the buffer. Dim mapLayerInfoArray() As ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo = mapServerInfo.MapLayerInfos Dim SchoolDistrictsLayerID As Integer = -1 Dim geometryFieldName As String = Nothing For Each mapLayerInfo As ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo In mapLayerInfoArray If mapLayerInfo.Name = "SchoolTaxDistrict" Then SchoolDistrictsLayerID = mapLayerInfo.LayerID For Each field As ESRI.ArcGIS.ADF.ArcGISServer.Field In mapLayerInfo.Fields.FieldArray If field.Type = ESRI.ArcGIS.ADF.ArcGISServer.esriFieldType.esriFieldTypeGeometry Then geometryFieldName = field.Name Exit For End If Next field Exit For End If Next mapLayerInfo ' Create and initialize a spatial filter with the buffer geometry and SchoolDistrict sites geometry ' field name Dim agsSoapSpatialFilter As New ESRI.ArcGIS.ADF.ArcGISServer.SpatialFilter() agsSoapSpatialFilter.FilterGeometry = agsSoapBufferGeometryArray(0) agsSoapSpatialFilter.SpatialRel = ESRI.ArcGIS.ADF.ArcGISServer.esriSpatialRelEnum.esriSpatialRelIntersects agsSoapSpatialFilter.GeometryFieldName = geometryFieldName ' Execute the query operation Dim agsSoapRecordSet As ESRI.ArcGIS.ADF.ArcGISServer.RecordSet = mapServerDcomProxy.QueryFeatureData(mapServerDcomProxy.GetDefaultMapName(), SchoolDistrictsLayerID, agsSoapSpatialFilter) ' #End Region ' #Region "Package function output based on SchoolDistrict site data" ' Get the indexes of School Description Field Dim schoolDscrpIndex As Integer = -1 Dim currentIndex As Integer = 0 For Each agsSoapField As ESRI.ArcGIS.ADF.ArcGISServer.Field In agsSoapRecordSet.Fields.FieldArray If agsSoapField.Name.ToUpper() = "SCHLDSCRP" Then schoolDscrpIndex = currentIndex Exit For End If currentIndex += 1 Next agsSoapField ' For each SchoolDistrict record, instantiate a new SchoolDistrict object and add it to the SchoolDistrict sites ' list object Dim SchoolDistrictsList As New System.Collections.ArrayList() Dim SchoolDistrict As SchoolDistrict = Nothing For Each SchoolDistrictRecord As ESRI.ArcGIS.ADF.ArcGISServer.Record In agsSoapRecordSet.Records SchoolDistrict = New SchoolDistrict(CStr(SchoolDistrictRecord.Values(schoolDscrpIndex))) SchoolDistrictsList.Add(SchoolDistrict) Next SchoolDistrictRecord ' Copy the SchoolDistrict sites list to an array to be returned as the function result Dim SchoolDistrictsArray(SchoolDistrictsList.Count - 1) As SchoolDistrict SchoolDistrictsList.CopyTo(SchoolDistrictsArray) ' #End Region ' Release server contexts mapServerContext.ReleaseContext() geocodeServerContext.ReleaseContext() geometryServerContext.ReleaseContext() Return SchoolDistrictsArray Catch exception As System.Exception System.Diagnostics.Debug.WriteLine("Exception: " & exception.Message) Finally ' Make sure server contexts are released If mapServerContext IsNot Nothing Then mapServerContext.ReleaseContext() End If If geocodeServerContext IsNot Nothing Then geocodeServerContext.ReleaseContext() End If If geometryServerContext IsNot Nothing Then geometryServerContext.ReleaseContext() End If End Try Return Nothing End Function End Class