ArcGIS_Geocode_Search_CSharp\App_Code\SchoolDistrictLocatorService.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. // [System.Web.Services.WebService(Namespace = "http://localhost/ArcGIS_SchoolDistrictGeocode_WebService/")] [System.Web.Services.WebServiceBinding(ConformsTo = System.Web.Services.WsiProfiles.BasicProfile1_1)] public class SchoolDistrictLocatorService : System.Web.Services.WebService { public SchoolDistrictLocatorService(){} [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 SchoolDistrict[] FindSchoolDistrictLocationsArcObjects(string FullAddress, string Distance) { // Make sure all inputs were specified if (FullAddress == null || string.IsNullOrEmpty(Distance.ToString()) || System.Convert.ToDouble(Distance) == 0.0) { return null; } // Declare server context variables ESRI.ArcGIS.Server.IServerContext mapServerContext = null; ESRI.ArcGIS.Server.IServerContext geocodeServerContext = null; ESRI.ArcGIS.Server.IServerContext geometryServerContext = null; try { // Connect to ArcGIS Server ESRI.ArcGIS.ADF.Identity adfIdentity = new ESRI.ArcGIS.ADF.Identity("username", "password", "domainOrmachine"); ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection agsServerConnection = 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 ESRI.ArcGIS.Server.IServerObjectManager serverObjectManager = 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"); ESRI.ArcGIS.Location.IGeocodeServer geocodeServer = geocodeServerContext.ServerObject as ESRI.ArcGIS.Location.IGeocodeServer; // Instantate and populate a property set holding geocode operation input parameters ESRI.ArcGIS.esriSystem.IPropertySet aoInputPropertySet = geocodeServerContext.CreateObject("esriSystem.PropertySet") as ESRI.ArcGIS.esriSystem.IPropertySet; aoInputPropertySet.SetProperty("Single Line Input", FullAddress); // Execute the geocoding operation ESRI.ArcGIS.esriSystem.IPropertySet aoResultsPropertySet = geocodeServer.GeocodeAddress(aoInputPropertySet, null); // Retrieve the geocoded point from the operation results ESRI.ArcGIS.Geometry.IPoint aoLocationPoint = aoResultsPropertySet.GetProperty("Shape") as ESRI.ArcGIS.Geometry.IPoint; #endregion #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. ESRI.ArcGIS.Geometry.IPoint aoLocationPointInGeometryServer = (ESRI.ArcGIS.Geometry.IPoint) geometryServerContext.LoadObject(geocodeServerContext.SaveObject(aoLocationPoint)); ESRI.ArcGIS.Geometry.IGeometryServer geometryServer = geometryServerContext.ServerObject as 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. ESRI.ArcGIS.Geometry.ISpatialReference aoBufferSpatialReference = 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. ESRI.ArcGIS.Geometry.ISpatialReference outputSpatialReference = 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"); ESRI.ArcGIS.Carto.IMapServer2 mapServer = mapServerContext.ServerObject as ESRI.ArcGIS.Carto.IMapServer2; // Get a reference to the map service's server info object ESRI.ArcGIS.Carto.IMapServerInfo mapServerInfo = mapServer.GetServerInfo(mapServer.DefaultMapName); // Create a spatial reference environemnt for use by the ConvertUnitType method ESRI.ArcGIS.Geometry.SpatialReferenceEnvironment spatialReferenceEnvironment = geometryServerContext.CreateObject("esriGeometry.SpatialReferenceEnvironment") as ESRI.ArcGIS.Geometry.SpatialReferenceEnvironment; // Convert the map service's units to the type required by the buffer operation ESRI.ArcGIS.Geometry.IUnit bufferUnit = Utility.ConvertUnitType(mapServerInfo.MapUnits, spatialReferenceEnvironment); // Package the geocoded point and buffer distance in arrays to pass to the buffer // operation ESRI.ArcGIS.Geometry.IGeometryArray aoInputGeometryArray = geometryServerContext.CreateObject("esriGeometry.GeometryArray") as ESRI.ArcGIS.Geometry.IGeometryArray; aoInputGeometryArray.Add(aoLocationPointInGeometryServer); ESRI.ArcGIS.esriSystem.IDoubleArray distancesArray = geometryServerContext.CreateObject("esriSystem.DoubleArray") as ESRI.ArcGIS.esriSystem.IDoubleArray; distancesArray.Add(System.Convert.ToDouble(Distance)); // Execute the buffer operation ESRI.ArcGIS.Geometry.IGeometryArray aoBufferGeometryArray = geometryServer.Buffer( aoLocationPointInGeometryServer.SpatialReference, aoBufferSpatialReference, outputSpatialReference, distancesArray, bufferUnit, false, aoInputGeometryArray); // Retrieve the buffer geometry from the operation results ESRI.ArcGIS.Geometry.IPolygon aoBuffer = aoBufferGeometryArray.get_Element(0) as 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. ESRI.ArcGIS.Geometry.IPolygon aoBufferInMapServer = (ESRI.ArcGIS.Geometry.IPolygon) mapServerContext.LoadObject(geometryServerContext.SaveObject(aoBuffer)); #endregion #region Find SchoolDistrict sites within the buffer // Retrieve the map service's MapLayerInfos object to use in accessing information about // the service's layers ESRI.ArcGIS.Carto.IMapLayerInfos mapLayerInfos = 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. int SchoolDistrictsLayerID = -1; string geometryFieldName = null; for (int i = 0; i < mapLayerInfos.Count; i++) { ESRI.ArcGIS.Carto.IMapLayerInfo mapLayerInfo = mapLayerInfos.get_Element(i); if (mapLayerInfo.Name == "SchoolTaxDistrict") { SchoolDistrictsLayerID = mapLayerInfo.ID; for (int j = 0; j < mapLayerInfo.Fields.FieldCount; j++) { ESRI.ArcGIS.Geodatabase.IField field = mapLayerInfo.Fields.get_Field(j); if (field.Type == ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGeometry) { geometryFieldName = field.Name; break; } } break; } } // Instantiate and initialize a spatial filter with the buffer geometry and SchoolDistrict sites // layer geometry field name ESRI.ArcGIS.Geodatabase.ISpatialFilter aoSpatialFilter = mapServerContext.CreateObject("esriGeodatabase.SpatialFilter") as ESRI.ArcGIS.Geodatabase.ISpatialFilter; aoSpatialFilter.Geometry = aoBufferInMapServer; aoSpatialFilter.SpatialRel = ESRI.ArcGIS.Geodatabase.esriSpatialRelEnum.esriSpatialRelIntersects; aoSpatialFilter.GeometryField = geometryFieldName; // Execute the query ESRI.ArcGIS.Geodatabase.IRecordSet aoRecordSet = mapServer.QueryFeatureData( mapServer.DefaultMapName, SchoolDistrictsLayerID, aoSpatialFilter); #endregion #region Package function output based on SchoolDistrict site data // Retrieve the School Description type fields int schoolDscrpIndex = -1; int currentIndex = 0; for (int i = 0; i < aoRecordSet.Fields.FieldCount; i++) { ESRI.ArcGIS.Geodatabase.IField field = aoRecordSet.Fields.get_Field(i); if (field.Name.ToUpper() == "SCHLDSCRP") { schoolDscrpIndex = currentIndex; break; } currentIndex++; } System.Collections.ArrayList SchoolDistrictsList = new System.Collections.ArrayList(); SchoolDistrict SchoolDistrict = null; // Get a cursor to loop through the rows corresponding to SchoolDistrict site results ESRI.ArcGIS.Geodatabase.ICursor SchoolDistrictCursor = aoRecordSet.get_Cursor(false); ESRI.ArcGIS.Geodatabase.IRow SchoolDistrictRow = SchoolDistrictCursor.NextRow(); // For each SchoolDistrict site record, instantiate a new SchoolDistrict object and add it to the SchoolDistrict sites // list object while (SchoolDistrictRow != null) { SchoolDistrict = new SchoolDistrict((string)SchoolDistrictRow.get_Value(schoolDscrpIndex)); SchoolDistrictsList.Add(SchoolDistrict); SchoolDistrictRow = SchoolDistrictCursor.NextRow(); } // Copy the SchoolDistrict sites list to an array to be returned as the function result SchoolDistrict[] SchoolDistrictsArray = new SchoolDistrict[SchoolDistrictsList.Count]; SchoolDistrictsList.CopyTo(SchoolDistrictsArray); #endregion return SchoolDistrictsArray; } catch (System.Exception exception) { System.Diagnostics.Debug.WriteLine("Exception: " + exception.Message); } finally { // Make sure server contexts are released if (mapServerContext != null) mapServerContext.ReleaseContext(); if (geocodeServerContext != null) geocodeServerContext.ReleaseContext(); if (geometryServerContext != null) geometryServerContext.ReleaseContext(); } return null; } [System.Web.Services.WebMethod(Description = "Locates SchoolDistrict sites 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 SchoolDistrict[] FindSchoolDistrictLocationsSoap(string FullAddress, double Distance) { // Check to make sure all inputs are specified if (FullAddress == null || string.IsNullOrEmpty(Distance.ToString()) || System.Convert.ToDouble(Distance) == 0.0) { return null; } // Declare server context variables ESRI.ArcGIS.Server.IServerContext mapServerContext = null; ESRI.ArcGIS.Server.IServerContext geocodeServerContext = null; ESRI.ArcGIS.Server.IServerContext geometryServerContext = null; try { // Open a connection to ArcGIS Server ESRI.ArcGIS.ADF.Identity adfIdentity = new ESRI.ArcGIS.ADF.Identity("username", "password", "domainOrmachine"); ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection agsServerConnection = 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 ESRI.ArcGIS.Server.IServerObjectManager serverObjectManager = agsServerConnection.ServerObjectManager; #region Geocode the input address // Create an ArcGIS Server SOAP property set to hold the input to the geocode oparation ESRI.ArcGIS.ADF.ArcGISServer.PropertySet agsSoapInputPropertySet = new ESRI.ArcGIS.ADF.ArcGISServer.PropertySet(); agsSoapInputPropertySet.PropertyArray = new ESRI.ArcGIS.ADF.ArcGISServer.PropertySetProperty[1]; // Specify the street property ESRI.ArcGIS.ADF.ArcGISServer.PropertySetProperty agsSoapInputProperty = 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 ESRI.ArcGIS.ADF.ArcGISServer.GeocodeServerDcomProxy geocodeServerDcomProxy = new ESRI.ArcGIS.ADF.ArcGISServer.GeocodeServerDcomProxy(geocodeServerContext, true); // Execute the geocoding operation ESRI.ArcGIS.ADF.ArcGISServer.PropertySet agsSoapResultsPropertySet = geocodeServerDcomProxy.GeocodeAddress(agsSoapInputPropertySet, null); // Retrieve the geocoded point from the results array ESRI.ArcGIS.ADF.ArcGISServer.PointN agsSoapLocationPoint = null; for (int i = 0; i < agsSoapResultsPropertySet.PropertyArray.Length; i++) { if (agsSoapResultsPropertySet.PropertyArray[i].Key == "Shape") agsSoapLocationPoint = agsSoapResultsPropertySet.PropertyArray[i].Value as ESRI.ArcGIS.ADF.ArcGISServer.PointN; } #endregion #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 ESRI.ArcGIS.ADF.ArcGISServer.MapServerDcomProxy mapServerDcomProxy = new ESRI.ArcGIS.ADF.ArcGISServer.MapServerDcomProxy(mapServerContext, true); ESRI.ArcGIS.ADF.ArcGISServer.MapServerInfo mapServerInfo = mapServerDcomProxy.GetServerInfo(mapServerDcomProxy.GetDefaultMapName()); // Convert the service's units into the type required for the buffer operation ESRI.ArcGIS.ADF.ArcGISServer.LinearUnit bufferDistanceUnits = 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"); ESRI.ArcGIS.ADF.ArcGISServer.GeometryServerDcomProxy geometryServerDcomProxy = 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. ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference agsSoapSpatialReference = Utility.CreateOperationSpatialReference(agsSoapLocationPoint, geometryServerDcomProxy); // Package the geocoded point and buffer distance in arrays for passing to the buffer // operation ESRI.ArcGIS.ADF.ArcGISServer.Geometry[] agsSoapInputGeometryArray = new ESRI.ArcGIS.ADF.ArcGISServer.Geometry[1]; agsSoapInputGeometryArray[0] = agsSoapLocationPoint; double[] distancesArray = new double[1]; distancesArray[0] = Distance; // Output spatial reference for the buffer operation ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference outputSpatialReference = agsSoapLocationPoint.SpatialReference; // Execute the buffer operation ESRI.ArcGIS.ADF.ArcGISServer.Geometry[] agsSoapBufferGeometryArray = geometryServerDcomProxy.Buffer(agsSoapLocationPoint.SpatialReference, agsSoapSpatialReference, outputSpatialReference, distancesArray, bufferDistanceUnits, false, agsSoapInputGeometryArray); #endregion #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. ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo[] mapLayerInfoArray = mapServerInfo.MapLayerInfos; int SchoolDistrictsLayerID = -1; string geometryFieldName = null; foreach (ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo mapLayerInfo in mapLayerInfoArray) { if (mapLayerInfo.Name == "SchoolTaxDistrict") { SchoolDistrictsLayerID = mapLayerInfo.LayerID; foreach (ESRI.ArcGIS.ADF.ArcGISServer.Field field in mapLayerInfo.Fields.FieldArray) { if (field.Type == ESRI.ArcGIS.ADF.ArcGISServer.esriFieldType.esriFieldTypeGeometry) { geometryFieldName = field.Name; break; } } break; } } // Create and initialize a spatial filter with the buffer geometry and SchoolDistrict sites geometry // field name ESRI.ArcGIS.ADF.ArcGISServer.SpatialFilter agsSoapSpatialFilter = 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 ESRI.ArcGIS.ADF.ArcGISServer.RecordSet agsSoapRecordSet = mapServerDcomProxy.QueryFeatureData( mapServerDcomProxy.GetDefaultMapName(), SchoolDistrictsLayerID, agsSoapSpatialFilter); #endregion #region Package function output based on SchoolDistrict site data // Get the indexes of School Description Field int schoolDscrpIndex = -1; int currentIndex = 0; foreach (ESRI.ArcGIS.ADF.ArcGISServer.Field agsSoapField in agsSoapRecordSet.Fields.FieldArray) { if (agsSoapField.Name.ToUpper() == "SCHLDSCRP") { schoolDscrpIndex = currentIndex; break; } currentIndex++; } // For each SchoolDistrict record, instantiate a new SchoolDistrict object and add it to the SchoolDistrict sites // list object System.Collections.ArrayList SchoolDistrictsList = new System.Collections.ArrayList(); SchoolDistrict SchoolDistrict = null; foreach (ESRI.ArcGIS.ADF.ArcGISServer.Record SchoolDistrictRecord in agsSoapRecordSet.Records) { SchoolDistrict = new SchoolDistrict((string)SchoolDistrictRecord.Values[schoolDscrpIndex]); SchoolDistrictsList.Add(SchoolDistrict); } // Copy the SchoolDistrict sites list to an array to be returned as the function result SchoolDistrict[] SchoolDistrictsArray = new SchoolDistrict[SchoolDistrictsList.Count]; SchoolDistrictsList.CopyTo(SchoolDistrictsArray); #endregion // Release server contexts mapServerContext.ReleaseContext(); geocodeServerContext.ReleaseContext(); geometryServerContext.ReleaseContext(); return SchoolDistrictsArray; } catch (System.Exception exception) { System.Diagnostics.Debug.WriteLine("Exception: " + exception.Message); } finally { // Make sure server contexts are released if (mapServerContext != null) mapServerContext.ReleaseContext(); if (geocodeServerContext != null) geocodeServerContext.ReleaseContext(); if (geometryServerContext != null) geometryServerContext.ReleaseContext(); } return null; } }