Friday, September 10, 2010

ve: adding mappoint geocoding service

Posted by david on 21. January 2009 09:11

target is this: Precise Geocoding with MapPoint Web Service and Virtual Earth … I got a little lost with the web config setup, so I am also referencing this.Reflect() & this MSDN Step 1 Set Up the Project for the Federated Search Virtual Earth Map Connector [Search Server 20

“The code also uses the <appSettings> section of the application's Web.config file to locate the user ID and password for the MapPoint Web Service. To use this code in your application, you'll need to add an <appSettings> element to your Web.config file. Here's a sample:

		<appSettings>  <add key="MPUser" value="UserID" />  <add key="MPPass" value="Password" /></appSettings>	
	

You would need to replace the values with the user ID and password that you received from Microsoft when you signed up for your evaluation account.” ( source )

That seemed to work … got the web reference added, the user info in to webconfig, and updating the web reference did not error out.

Now to create the geocoding class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
public class RooftopGeocoder
{
    private MapPointService.FindServiceSoap findService;
 
    public RooftopGeocoder()
    {
        findService = new MapPointService.FindServiceSoap();
        findService.Credentials = new System.Net.NetworkCredential("username", "password");
        findService.PreAuthenticate = true;
    }
}

The MapPointService in “findService = new MapPointService.FindServiceSoap();” is failing “The type or namespace name 'MapPointService' could not be found (are you missing a using directive or an assembly reference?”

tried wrapping the RooftopGeocoder class in a namespace RooftopGeocoder. Following this model:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Configuration;
using MapPointGeocode.MapPointService;
using System.Web.Services.Protocols;
using System.Diagnostics;
 
namespace MapPointGeocode
{
    public class MapPointGeocode
    {
        /// <summary>
        /// These are the actual instances of the objects that call the MapPoint .NET service
        /// </summary>
        private MapPointService.RenderServiceSoap renderService;
        private MapPointService.FindServiceSoap findService;
        
 
 
        public MapPointGeocode()
        {
            InstantiateServices();
        }
 
        private void InstantiateServices()
        {
            // Create and set the logon information (note comment in web.config -- here would be the place to
            // decrypt/unhash the user/password from the config file).
            //NEW - Revised configuration settings (add ref to System.Configuration first):
 
            NetworkCredential ourCredentials = new NetworkCredential(ConfigurationManager.AppSettings["MPUser"], ConfigurationManager.AppSettings["MPPass"]);
 
            // Create the render service, pointing at the correct location
            renderService = new MapPointService.RenderServiceSoap();
            renderService.Credentials = ourCredentials;
            renderService.PreAuthenticate = true;
 
            // Create the find service, pointing at the correct location
            findService = new MapPointService.FindServiceSoap();
            // set the logon information
            findService.Credentials = ourCredentials;
            findService.PreAuthenticate = true;
        }
 
        /// <summary>
        /// Returns the geocode coordinates of an address. 
        /// </summary>
        /// <param name="addressLine">The address</param>
        /// <param name="city">The city</param>
        /// <param name="postalCode">The postal/zip code</param>
        /// <param name="country">The country. e.g.: USA, Canada</param>
        public LatLong GeocodeAddress(string addressLine, string city, string state, string postalCode, string country)
        {
            // Set up the address
            Address address = new Address();
            address.AddressLine = addressLine;
            address.PrimaryCity = city;
            address.PostalCode = postalCode;
            address.Subdivision = state; 
            address.CountryRegion = country;
 
            // Set up the specification for the address
            // Set up the specification object.
            FindAddressSpecification findAddressSpec = new FindAddressSpecification();
            findAddressSpec.InputAddress = address;
            findAddressSpec.DataSourceName = "MapPoint.NA"; // More info: http://msdn2.microsoft.com/en-us/library/ms982198.aspx and http://msdn2.microsoft.com/en-us/library/aa493004.aspx
 
            // Set the find options. Allow more return values by decreasing
            // the value of the ThresholdScore option.
            // Also, limit the number of results returned to 20.
            FindOptions myFindOptions = new FindOptions();
            myFindOptions.ThresholdScore = 0.5;
            myFindOptions.Range = new FindRange();
            myFindOptions.Range.StartIndex = 0;
            myFindOptions.Range.Count = 20;
            findAddressSpec.Options = myFindOptions;
 
            // Create a FindResults object to store the results of the FindAddress request.
            FindResults myFindResults;
            LatLong latLong = new LatLong(); 
 
            try
            {
                // Get the results and return them if there are any. 
                myFindResults = findService.FindAddress(findAddressSpec);
                FindResult[] myResults = myFindResults.Results;
                if(myResults!= null)
                {
                    latLong = myResults[0].FoundLocation.LatLong;
                }
                
            }
            catch (SoapException myException)
            {
                // Your exception handling process goes here.
                Debug.Write(myException);
            }
 
            return latLong; 
        }
    }
}

resulting in:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.Net;
using System.Configuration;
using RooftopGeocoder.MapPointService;
using System.Web.Services.Protocols;
using System.Diagnostics;
 
namespace RooftopGeocoder
{
    public class RooftopGeocoder
    {
        private MapPointService.FindServiceSoap findService;
 
        public RooftopGeocoder()
        {
            findService = new MapPointService.FindServiceSoap();
            findService.Credentials = new System.Net.NetworkCredential("username", "password");
            findService.PreAuthenticate = true;
        }
    }
}

Still fails: “The type or namespace name 'MapPointService' does not exist in the namespace 'RooftopGeocoder' (are you missing an assembly reference?) “

I feel like I am blindfolded, trying to walk here, and maybe a little drunk too.

C# Frequently Asked Questions Why did I receive the error The type or namespace 'namespace name'

followed this, but didn’t help.

Delete all web references.

Add new web reference:

http://staging.mappoint.net/standard-30/mappoint.wsdl

name the webreference “MapPointService” in the add web reference dialogue

here’s what I get:

app_webreferences

goddamnit – it’s working … but I didn’t see exactly which change made the difference – I hate that.

However, moving on, there are no squiggly red lines in this code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.Net;
using System.Configuration;
using RooftopGeocoder;
using System.Web.Services.Protocols;
using System.Diagnostics;
 
 
namespace RooftopGeocoder
{
    public class RooftopGeocoder
    {
        private MapPointService.FindServiceSoap findService;
 
        public RooftopGeocoder()
        {
            findService = new MapPointService.FindServiceSoap();
            findService.Credentials = new System.Net.NetworkCredential("username", "password");
            findService.PreAuthenticate = true;
        }
    }
}

Doing a build, just in case, is successful.

So, still following the RooftopGeocoder, next step is to create a method to do the geocode, returning a latlong

public string GeocodePoint(string streetAddress)
{
    string latlong = "Unavailable";
 
    //Define the address specification for MWS
    MapPointService.Address myAddress = new MapPointService.Address();
    myAddress.FormattedAddress = streetAddress;
 
    //Set the search options
    MapPointService.FindOptions myFindOptions = new MapPointService.FindOptions();
 
    MapPointService.FindAddressSpecification findAddressSpec =
     new MapPointService.FindAddressSpecification();
    findAddressSpec.InputAddress = myAddress;
    findAddressSpec.Options = myFindOptions;
    findAddressSpec.DataSourceName = "MapPoint.NA";
 
    //Set the ResultMask to include the rooftop geocoding values
    findAddressSpec.Options.ResultMask =
        MapPointService.FindResultMask.RooftopFlag |
        MapPointService.FindResultMask.LatLongFlag |
        MapPointService.FindResultMask.EntityFlag |
        MapPointService.FindResultMask.MatchDetailsFlag |
        MapPointService.FindResultMask.AddressFlag;
 
    //Call the MWS FindAddress method
    MapPointService.FindResults myFindResults = findService.FindAddress(findAddressSpec);
 
    //Parse the Results
    MapPointService.FindResult bestResult = myFindResults.Results[0];
    int matchcode = 0;
 
    MapPointService.EntityPropertyValue[] props =
      bestResult.BestViewableLocation.Entity.Properties;
    //Find MatchedMethod property which tells you whether rooftop was used 
    for (int i = 0; i < props.Length; i++)
    {
        if (props[i].Name == "MatchedMethod")
        {
            matchcode = System.Convert.ToInt32(props[i].Value);
        }
    }
    //Prepare result 
    if (matchcode == 7)
    {
        latlong = "new VELatLong(" + bestResult.BestViewableLocation.LatLong.Latitude
            + ", " + bestResult.BestViewableLocation.LatLong.Longitude + ")";
    }
    return latlong;
}     

adding this into the class worked fine, no obvious errors.  

still following the RooftopGeocoder, next step is to create an HttpHandler that will use the RooftopGeocoder class.  To the project, Add New Item, Generic Handler, named GeocodingHandler:

using System;
using System.Web;
 
public class GeocodingHandler : IHttpHandler {
 
    public void ProcessRequest(HttpContext context)
    {
        RooftopGeocoder rg = new RooftopGeocoder();
        context.Response.ContentType = "text/plain";
        string result = rg.GeocodePoint(context.Request.QueryString["addr"]);
        context.Response.Write("CreatePin('Rooftop', " + result + ")");
    }
 
    public bool IsReusable {
        get {
            return false;
        }
    }
   
    
}

no glaring errors.  but i see that my easy copy and paste days are probably over:

“Notice that we pass the "addr" querystring parameter to an instance of RooftopGeocoder. We take the returned VELatLong object and pass it back to a JavaScript method called "CreatePin". We'll write that method in the next section.” ( source )

It’s time to figure out how to use the webservice myself.  The RooftopGeocoder code I’ve been referencing is built for a a javascript VEMap, using a text input box where user can enter an address & presses a button to get a pushpin.  Interesting, they use two methods to get two pushpins – one via Rooftop, one via default VE geocoding. & there seems to be a significant difference.

A summary blurb about the Rooftop methods:

“The sample code in this article illustrates two key points. First, you can use the AJAX framework illustrated here to connect your Virtual Earth system to any data source. Whether you are connecting indirectly to MapPoint Web Service, or connect to your own database, or even a third party data service, you can display the data on your Virtual Earth map.

Second, you can leverage MapPoint Web Service's advanced rooftop geocoding. All you need to do is:

  1. Set up a MapPoint Web Service account
  2. Create a class to perform the geocoding
  3. Write the AJAX plumbing for both the server side (HttpHandler) and client side.

Following these simple steps, you could also leverage other components of MapPoint Web Service, including alternate map views, "line drive" driving directions, and the extended points of interest data sets.” ( source

aside : wonder how to link to a section in a page .. like the bottom summary.  anchor? but there doesn’t seem to be one.

I’ll break here & take up the “making it work” in the next post.

Comments

Add comment


 

biuquote
Loading