text: Creating applications for mobile devices has its own set of unique challenges.
  Adding to the mix is the problem of maintaining connectivity over slow, expensive,
  and unreliable networks. Working with web services and other network protocols
  that were designed with broadband in mind can become a real burden to making
  applications really mobile. But there is hope; in this article, we will walk
  through the design and implementation of a complete end-to-end mobile application.
  It illustrates the common architecture and coding techniques for web-services-
  driven, smart mobile clients.
  The wide adoption of the .NET Compact Framework on Windows Mobile devices
  (including PocketPCs and Smartphones) enables us to extend the existing Web
  Services infrastructure to support end-to-end mobile applications. The .NET
  Compact Framework has some important advantages over legacy mobility technology
  platforms.
  Compared with micro-browser-based mobile thin clients, .NET-Compact-Framework-
  based smart clients are more reliable and faster because they are less dependent
  on the network and can cache aggressively to reduce network round trips. In today's
  unreliable, expensive, and slow wireless networks, offline operation
  capability is crucial to the success of a mobile application. In addition, smart
  clients offer richer user experiences via more interactive UIs that run locally
  on the device.
  Compared with C/C++ native applications, .NET smart clients are easier
  to develop and less prone to errors, thanks to the advanced programming language/tool
  support in .NET and the managed execution environment. Since mobile devices
  have limited memory space and processing power, most smart clients delegate
  some data- or computation-intensive tasks to back end servers. The .NET Compact
  Framework offers superb support for XML web services, which allows us to build
  connected smart clients that easily integrate into the existing service infrastructure.
  The .NET Compact Framework is specifically designed to follow the same application
  models and APIs that are available in the regular .NET framework. Together with
  familiar tools such as Visual Studio .NET 2003, it is very easy for a desktop
  or server-side .NET developer to get started with the Compact Framework. However,
  despite the apparent similarity in development environments, mobile devices
  and networks are different from PCs and Ethernets in several fundamental ways.
  Blind skill transfer from PCs to devices is often a source of frustration or
  even project failure. As developers, we have to understand the special requirements
  and characteristics of networked mobile applications. Now, let's first have
  a look at the sample application.
  The sample application is a driving directions application powered by
  the MapPoint web service. On a connected Windows Mobile device, it works as
  follows: the user taps from and to addresses into
  the UI form; the device queries a GIS (Geographic Information System) server,
  and then displays driving directions and turn-by-turn driving maps. It
  allows the user to look up driving directions any time, from anywhere in the field.
  Figure 1 shows the workflow.
  from
  to
  Figure 1. The workflow of the Driving Directions application
  The complete source code of the application is available from
  here. To build and test the front-end mobile smart client, you have to
  have Visual Studio .NET 2003 and the PocketPC 2003 and Smartphone 2003 SDKs
  installed. Both SDKs are freely available from
  Microsoft's mobility web site.
  At the back end, the
  Microsoft MapPoint web service, a hosted GIS solution, drives the
  application. A GIS server stores and processes geographic information. For
  example, the GIS server can: convert a street address to a pair of longitude and
  latitude coordinates, and vice versa; find the best route to connect two addresses; check
  yellow pages listings against addresses; find out points of interest (e.g.,
  landmarks and shops) and potential hazards (e.g., construction sites and underground
  pipes) around a certain location or a route. GIS is widely used in military,
  city planning, construction, transportation, tourism, and many other industries.
  It helps planners to design the most efficient strategy and prepares field
  personnel for new environments. MapPoint takes care of the day-to-day GIS
  server management, as well as the licensing of up-to-date, high-resolution
  digital maps. Users pay for its services on a per-use or subscription basis. A
  big advantage of MapPoint is that it is accessible through an open SOAP web
  service interface. Being a web service ensures that MapPoint is ubiquitously available
  to a large variety of client and middleware applications.
  Although we make use of the MapPoint SOAP API in the sample application, API
  usage is not the focus of this article. Interested readers can find the C# and
  VB.NET API reference in the
  MapPoint SDK from MSDN. In order to run the application, you need a
  service account with MapPoint. You can sign up for a 45-day free evaluation
  account, replace the account credentials in the MPfacade.asmx.cs file
  with your own, and then re-build the application.
  MapPoint is a utility service. It offers fine-grained access to its GIS
  services. This allows us to write flexible applications without arbitrary
  limitations imposed by the API designer. However, the tradeoff is that we have
  to make many small-step method calls to complete a task. For example, in order
  to get driving directions between two addresses, we must complete the following
  steps:
  The last two steps need to be repeated many times for a long route with many
  segments. All of those calls are remote SOAP RPCs performed over the network. For
  clients that only need to perform simple, pre-scripted GIS tasks (e.g., our
  driving directions client), those RPC round trips are excessive and cause
  drastic performance degrade over wireless networks. Therefore, it is not
  advisable to access the MapPoint web service directly from mobile clients. To
  minimize the round trips over wireless networks, we place a remote facade in
  front of the MapPoint web service.
  A remote facade is a design pattern to provide a coarse-grained access interface
  to a set of complex remote subsystems. It is designed to shield the client from
  the complexity of subsystems. As a result, network round trips are greatly
  reduced. The facade pattern is probably the most widely used architectural
  pattern in end-to-end mobile applications. In our application, the facade takes
  in two human-readable addresses in a single RPC call from the wireless client,
  queries MapPoint via a sequence of remote calls over the wired Internet,
  constructs the resultant driving directions, and finally returns the results.
  The overall architecture and the facade call model are illustrated in Figure 2.
  Figure 2. Smart mobile application architecture
  FacadeServer
  In our example, the facade is implemented using ASP.NET web services. The FacadeService
  class in the project MPfacade supports web methods such as getSessDirections
  (i.e., get text directions) and getSessMap (i.e., get a map),
  which utilize the MapPoint web service to complete their tasks. To understand
  the MapPoint API calls in the facade, please refer to the MapPoint SDK. The
  facade essentially aggregates the complex MapPoint API into several simple web
  methods.
  FacadeService
  MPfacade
  getSessDirections
  getSessMap
  FacadeClient
  On the client side, we need to support both the PocketPC and Smartphone UIs.
  Those two UIs must be developed in two separate projects, since the two devices
  have different screen sizes and support different sets of designer widgets. To
  reuse the business layer code, we put all of the facade-client code in the FacadeClient
  project. Both UI projects contain references to the FacadeClient project.
  In the next section, we will discuss the interaction between the .NET Compact
  Framework client and the ASP.NET facade.
  At a glance, it is trivial to build a mobile client for the facade. We could
  just add the facade service as a web reference to the project FacadeClient.
  However, by default, remote web service calls are stateless. Each request is
  independent. Without remembering the user state, the server needs to start
  fresh for every new request. In our example, that means it must build the entire
  route over again every time the client requests a segment map; this is very
  inefficient. A much better solution is to cache the calculated route in the
  facade server. In a multi-user environment, we have to retrieve the correct
  route object from the cache for each user. That requires the facade server to
  recognize requests from the same user and group web service requests into
  sessions. It works as follows.
  When the client makes its first request, the server creates a session object
  and an ID. The ID is returned to the client. The client stores the ID and puts
  it in all subsequent requests to the same server. The server will then have a
  way to identify and link the request with session objects. The key is to
  exchange and keep track of session IDs. In the next two sections, we discuss
  two session tracking techniques: utilizing HTTP cookies and building session
  IDs into the RPC protocol.
  Since all of our web services calls in this example are made over the HTTP
  transport, we could leverage HTTP's built-in session tracking mechanism,
  HTTP cookies. Cookies are pieces of session identification strings embedded in
  HTTP headers. When the client makes its first connection, the ID is created and
  returned to the client via the HTTP Set-Cookie header. If the
  client is cookie-aware, it stores the cookie and puts it in the Cookie
  header in all subsequent requests. This is the best way to track sessions in
  ASP.NET applications, since the cookies are handled transparently to the
  application developers, and this makes efficient use of the HTTP infrastructure.
  To write cookie-aware ASP.NET web methods, we just need to add a true
  attribute in the method's meta data tag. A session object that is uniquely
  associated with the current cookie can be retrieved from the runtime context.
  We can cache the calculated route in the session object.
  Set-Cookie
  Cookie
  true
  private CachedRoute getCache() {
  CachedRoute cache = (CachedRoute) Session["CachedRoute"];
  // This is a new session
  if (cache == null)
  {
  cache = new CachedRoute ();
  Session["CachedRoute"] = cache;
  }
  return cache;
  }
  [WebMethod(true)]
  public String [] getSessDirections (String fromStreet, String fromCity,
  String fromState, String fromZip, String toStreet, String toCity,
  String toState, String toZip) {
  CachedRoute cache = getCache();
  return getDirections(cache, fromStreet, fromCity,
  fromState, fromZip, toStreet, toCity, toState, toZip);
  }
  All the client needs to do is to receive and remember the cookie. However, the
  .NET Compact Framework v1.0 HTTP client library does not have built-in cookie
  support (the CookieCollection object is not supported). In
  the .NET Compact Framework Service Pack 1 (SP1), which is built into Smartphone
  2003 but requires manual install on PocketPC 2003, the application developer
  can override the GetWebRequest and GetWebResponse methods
  in the VS.NET-generated SOAP client-proxy class. We can manually build a
  decorator class that subclasses the client proxy and add cookie-handling logic
  to the GetWebRequest/GetWebResponse methods. The code snippet below
  shows the cookie-aware decorator methods. FacadeService is the
  web service proxy class generated by VS.NET when we added the web reference.
  CookieCollection
  GetWebRequest
  GetWebResponse
  GetWebRequest/GetWebResponse
  public class SessionFacadeService : FacadeService
  {
  private static string cookie = null;
  protected override WebRequest GetWebRequest(Uri uri) {
  HttpWebRequest req = (HttpWebRequest) base.GetWebRequest(uri);
  if (cookie != null)
  {
  req.Headers.Add("Cookie", cookie);
  }
  return req;
  }
  protected override WebResponse GetWebResponse(WebRequest req) {
  HttpWebResponse rep = (HttpWebResponse) base.GetWebResponse(req);
  if (rep.Headers["Set-Cookie"] != null)
  {
  cookie = rep.Headers["Set-Cookie"];
  }
  return.