Section 5.3. Preparing Your Development Environment


5.3. Preparing Your Development Environment

Now that you know how to get started with MapPoint Web Service, let's look at how to prepare your development environment to develop MapPoint Web Service applications.

5.3.1. Adding a Web Reference

If you are developing managed code applications using Visual Studio .NET 2003 or later, programming with MapPoint Web Service is fairly straightforward; you can access the MapPoint Web Service by using the Add Web Reference option from the project context menu, as shown in Figure 5-3.

Figure 5-3. Add Web Reference context menu


When you see the Add Web Reference dialog window, type the MapPoint Web Service staging service URL in the URL textbox, as shown in Figure 5-4.

Once you type the staging service URL, and the WSDL document is parsed by Visual Studio, the documentation available within the WSDL document is shown in the preview pane. At this point, you can click the Add Reference button to add the MapPoint Web Service as a web reference to your project. When you click on the Add Reference button, Visual Studio .NET automatically creates a proxy class that can be used to program with MapPoint Web Service. By default, this proxy class is named Reference.cs (or Reference.vb) and is placed within the Web References directory created inside the project's root directory (this file can only be seen when the Show All Files mode is enabled in the Visual Studio .NET solution explorer). The location of the Reference.cs file is shown in Figure 5-5.

Figure 5-4. Adding MapPoint Web Service staging service as a web reference


If you are developing your applications using VB 6.0/ASP in unmanaged code, you can still use MapPoint Web Service; however, in this case, you need to use either COM Wrappers around the managed code proxy class or the Microsoft SOAP Toolkit.


This class file contains all the C# (or VB.NET) equivalents of the interface definitions in the WSDL document. For example, the MapPoint Web Service WSDL document contains a complex type to represent latitude and longitude:

     <s:complexType name="LatLong">       <s:sequence>        <s:element minOccurs="0" maxOccurs="1" default="0" name="Latitude" type="s:double" />        <s:element minOccurs="0" maxOccurs="1" default="0" name="Longitude" type="s:double" />      </s:sequence>    </s:complexType>

Figure 5-5. Proxy class file added by Visual Studio .NET


This type definition is represented as a class in the Reference.cs file:

     public class LatLong {      /// <remarks/>      [System.ComponentModel.DefaultValueAttribute(0)]      public System.Double Latitude = 0;      /// <remarks/>      [System.ComponentModel.DefaultValueAttribute(0)]      public System.Double Longitude = 0;     }

As you can see, the previous class is a pure programmatic type representation of the XSD type defined in the WSDL document. You can use this type in your applications as you can any other .NET type. Not all the classes in the proxy file (Reference.cs or Reference.vb) are pure type definitions with just structure information like LatLong class; there are also some classes with methods that you can invoke from your application, including CommonServiceSoap, FindServiceSoap, RouteServiceSoap, and RenderServiceSoap, which are derived from the SoapHttpClientProtocol class from the System.Web.Service.Protocols namespace. Each class has a constructor with the service URL hardcoded within it.

If you are not familiar with service URLs , they are the so-called "service endpoints " of a web service that offer remote methods that can be invoked in a distributed environment. For MapPoint Web Service, there are four service endpoints that map to the service class types specified previously. The service URL and service class type mapping are shown in Table 5-1.

Table 5-1. MapPoint web service endpoints

Service name

Class type

Service URL

Common Service

CommonServiceSoap

http://findv3.staging.mappoint.net/Find-30/Common.asmx

Find Service

FindServiceSoap

http://findv3.staging.mappoint.net/Find-30/FindService.asmx

Route Service

RouteServiceSoap

http://routev3.staging.mappoint.net/Route-30/RouteService.asmx

Render Service

RenderServiceSoap

http://renderv3.staging.mappoint.net/Render-30/RenderService.asmx


Each one of the above four types (classes) has a constructor with the service URL hardcoded in the constructor; for example, if you look for the constructor of the FindServiceSoap class in the Reference.cs file, you will find the definition as follows:

     public FindServiceSoap()     {       this.Url = "http://findv3.staging.mappoint.net/Find-30/FindService.asmx";     } 

When you invoke any methods on the FindServiceSoap class, a proxy class for the Find Service, you are remotely invoking methods on the MapPoint Web Service servers. However, if you look closely, the previously stated service URL is pointing to the MapPoint Web Service staging servers. When you want your application to work with the MapPoint Web Service production servers, you must change the URL to point to the production WSDL and recompile the application, which can be an issue if you want to switch between the staging and production environments without re-compiling the application each time you switch. However, it has a very simple workaroundjust make the service URL configurable.

5.3.1.1. Static versus dynamic service URL

After adding a web reference using Visual Studio .NET, you can choose whether to make the service URL dynamic, meaning that the proxy classes are generated such that the service URLs can be configured and managed via the config file (web.config for web applications and app.config for Windows applications). The default option is a static service URL. Figure 5-6 shows the web reference property to change the URL's behavior.

If you look at the FindServiceSoap constructor with the dynamic service URL option, the class constructor looks as follows:

     public FindServiceSoap()     {         string urlSetting =          System.Configuration.ConfigurationSettings.AppSettings["myapp.CommonService"];         if ((urlSetting != null))         { 

Figure 5-6. URL behavior setting


           this.Url = string.Concat(urlSetting, "FindService.asmx");         }         else        {         this.Url = "http://findv3.staging.mappoint.net/Find-30/FindService.asmx";        }     }

The constructor first tries to obtain the service URL from the configuration file, and when it can't find it in the configuration file, it reassigns the static service URL. It is important to note that only the non-asmx part of the service URL is made configurable, while the asmx (for example, FindService.asmx) filename is still hardcoded. To support this dynamic URL behavior, add the following application key in the configuration file to access staging MapPoint Web Service:

     <appSettings>       <add key="myapp.CommonService"         value="http://findv3.staging.mappoint.net/Find-30/"/>       </appSettings>     </configuration>

Along similar lines, add the following value to access the production MapPoint Web Service:

     <appSettings>       <add key="myapp.CommonService"         value="http://findv3.service.mappoint.net/Find-30/"/>       </appSettings>     </configuration>

To enable dynamic service URL behavior, in an ideal world, you would select the Dynamic option for the URL Behavior property from Visual Studio .NET, and you would be all setexcept that you aren't. The dynamic URL feature in Visual Studio .NET does not work for MapPoint Web Service. In Visual Studio .NET, the static/dynamic service URL feature was designed for web services with one service endpoint per WSDL document, which means there is only class that implements SoapHttpClientProtocol type per Reference.cs or Reference.vb file. Even if there is more than one service endpoint, the assumption was that the base URL of the service is always the same; however, for MapPoint Web Service, one WSDL actually points to four services that have three physical service endpoints . So, in order to make your MapPoint Web Service proxy class properly enabled with dynamic URL behavior, you need to do the following steps:

First, add the following key to your configuration file:

     <appSettings>       <add key="myapp.CommonService"         value="http://findv3.staging.mappoint.net/Find-30/Common.asmx"/>       <add key="myapp.FindService"         value="http://findv3.staging.mappoint.net/Find-30/Find.asmx"/>       <add key="myapp.RouteService"         value="http://routev3.staging.mappoint.net/Route-30/Route.asmx"/>       <add key="myapp.RenderService"         value="http://renderv3.staging.mappoint.net/Render-30/Render.asmx"/>     </appSettings>

Next, modify the service soap class constructors as shown below:

CommonServiceSoap class:

     public CommonServiceSoap() {       string urlSetting =         System.Configuration.ConfigurationSettings.AppSettings["myapp.CommonService"];       if ((urlSetting != null)) {          this.Url = urlSetting;       }       else {           this.Url = "http://findv3.staging.mappoint.net/Find-30/CommonService.asmx";       }     }

FindServiceSoap class:

     public FindServiceSoap() {       string urlSetting =         System.Configuration.ConfigurationSettings.AppSettings["myapp.FindService"];       if ((urlSetting != null)) {         this.Url = urlSetting;       }       else {           this.Url = "http://findv3.staging.mappoint.net/Find-30/FindService.asmx";       }     }

RouteServiceSoap class:

     public RouteServiceSoap() {       string urlSetting =        System.Configuration.ConfigurationSettings.AppSettings["myapp.RouteService"];       if ((urlSetting != null)) {         this.Url = urlSetting;       }       else {           this.Url = "http://routev3.staging.mappoint.net/route-30/RouteService.asmx";       }     }

RenderServiceSoap class:

     public RenderServiceSoap() {       string urlSetting =        System.Configuration.ConfigurationSettings.AppSettings["myapp.RenderService"];       if ((urlSetting != null)) {         this.Url = urlSetting;       }       else {           this.Url =            "http://renderv3.staging.mappoint.net/render-30/RenderService.asmx";       }     }

With this code in place, your application uses the service URL specified in the configuration file; when no configuration setting is found, staging service URLs are used instead.

Before we move to the next section, it is important to note that the modifications that you make to the Reference.cs or Reference.vb file are not persisted when you refresh the web reference. Be careful when you refresh the MapPoint Web Service web reference.

5.3.1.2. Storing your credentials securely

You need to secure MapPoint Web Service credentials through proper application configuration. MapPoint Web Service is a subscription-based web service, and each of your MapPoint Web Service requests must be authenticated to obtain a valid

Using WSDL.EXE

If you do not have Visual Studio .NET, you can still create a proxy class using the WSDL.EXE utility that ships with the .NET Framework SDK. You can find this utility in the bin directory of your .NET Framework SDK, and you can generate a proxy class by using the following command line:

WSDL.EXE /l:CS http://staging.mappoint.net/standard-30/mappoint.wsdl /out:C:\MapPointWebServiceProxy.cs

To generate a VB.NET proxy class, use the following command:

WSDL.EXE /l:VB http://staging.mappoint.net/standard-30/mappoint.wsdl /out:C:\MapPointWebServiceProxy.vb


response; for this purpose, MapPoint Web Service uses digest authentication. When you make a web service method call, you must assign your credentials to the service class.

For example, if you are invoking the Find method on the FindServiceSoap class, you need to assign your MapPoint Web Service credentials before calling the method:

     //Create service class instance     FindServiceSoap findservice = new FindServiceSoap();     //Assign credentials - Do not do this!     findservice.Credentials =        new System.Net.NetworkCredential("yourid", "yourpassword");     //Invoke the method     findservice.find(...);

In this code, the credentials are assigned using the System.Net.NetworkCredential object by hardcoding the user ID and password. There is a maintenance risk associated with this approach; for security reasons, you are required to change your MapPoint Web Service account password once every 45 to 60 days. When the time comes to change your password, you need to update the password and re-compile. In order to avoid these maintenance headaches, make the user ID and password configurable from a configuration file (app.config or web.config). Storing the user ID and password in clear text in the configuration file may pose a security threat, so you need to store the credentials in the configuration file in encrypted form.

There are multiple ways of encrypting your MapPoint Web Service ID and password. In any case, you must develop an encryption library using either the Data Protection APIs or Encryption APIs . The simplest way, of course, is to use the Windows Data Protection APIs (DPAPI ). The DPAPI support two kinds of entropies : machine store entropy and user store entropy . In both cases, you can also provide private entropy , which adds an additional layer of security.

For a detailed description of DPAPI and Encryption API programming, along with other security recommendations for online web applications, check out the Microsoft Patterns and Practices Guide online: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetHT07.asp?frame=true.


Since the Data Protection APIs are Win32 APIs, you need to build C# wrappers around them. A sample implementation of the DPAPI is included in the companion material (project Chapter05); the DataProtectionCore sample class can be used for encrypting and decrypting the MapPoint Web Service ID and password. The following code shows how to encrypt any given string using the DataProtectionCore sample class:

     public static string Encrypt(string input)     {       Chapter05.EncryptionUtil.DataProtectorCore dp       = new Chapter05.EncryptionUtil.DataProtectorCore(           Chapter05.EncryptionUtil.Store.USE_MACHINE_STORE);        byte[] encryptedBuffer =            dp.Encrypt(System.Text.ASCIIEncoding.ASCII.GetBytes(input),                         null);        return Convert.ToBase64String(encryptedBuffer);     }

Once the user ID and password are encrypted as shown in the previous code, you can store them in the configuration file as follows:

     <configuration>       <appSettings>         <add key="MapPointWebServiceID"               value="CAAAAAAADZgAAqAAAQ....tYt9br2PpFHM0AXJd/tIJ/bbb74="/>         <add key="MapPointWebServicePassword"               value="AQAAANCMnd8BFdE ....HTPITIgU6FQcAXJd/tIJXteE8/wQ=="/>       </appSettings>     </configuration>

Now your MapPoint Web Service ID and password are secure in the configuration file; however, your MapPoint Web Service application cannot readily use the encrypted MapPoint Web Service ID and password from the configuration file. You need to write a decrypt routine:

     public static string Decrypt(string input)     {        Chapter05.EncryptionUtil.DataProtectorCore dp        = new Chapter05.EncryptionUtil.DataProtectorCore(           Chapter05.EncryptionUtil.Store.USE_MACHINE_STORE);        byte[] decryptedBuffer = dp.Decrypt(Convert.FromBase64String(input)                          , null);        return System.Text.Encoding.ASCII.GetString(decryptedBuffer);     }

In this routine, the input string is decrypted back to the original ASCII text. Once you have this decrypt routine, you can always read the encrypted MapPoint Web Service ID and password, decrypt them, and pass them to the MapPoint Web Service:

     //Create a find service instance     FindServiceSoap find = new FindServiceSoap();     //Assign credentials     find.Credentials = new System.Net.NetworkCredential(     Decrypt(ConfigurationSettings.AppSettings["MapPointWebServiceID"]),     Decrypt(ConfigurationSettings.AppSettings["MapPointWebServicePassword"]));     . . .     //Find places     FindResults results = find.Find(spec);

The Encrypt and Decrypt methods are available in the companion material in the Chapter05 class.

5.3.1.3. Preauthenticate requests for performance gains

Finally, for performance reasons, always assign the PreAuthenticate property on the service SOAP class to True so that your application can avoid any extraneous round-trips to the server just for authentication. For example, on FindServiceSoap service class, set the value as shown:

     findservice.PreAuthenticate = true;

Now that you know how to prepare your development environment for MapPoint Web Service application development, let's get into the MapPoint Web Service object model before we start programming.




Programming MapPoint in  .NET
Programming MapPoint in .NET
ISBN: 0596009062
EAN: 2147483647
Year: 2005
Pages: 136
Authors: Chandu Thota

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net