How to connect to Bing Maps using Windows::Web::Http::HttpClient (Windows Runtime apps using C++ and XAML)

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

Connect to Bing Maps using the Windows::Web::Http::HttpClient class in the Windows::Web::Http::HttpClient namespace.

Prerequisites

The following examples use C++ and are based loosely on the HttpClient Sample. For general help creating a Windows Runtime app using C++, see Create your first Windows Runtime app using C++.

To ensure your Windows Runtime app is network ready, you must set any network capabilities that are needed in the project Package.appxmanifest file. For more information, see How to set network capabilities.

Create an account with the Bing Maps Location API and obtain a key

If you haven't done so already, you need to first get a key that your app will use to access the service. Follow the instructions in Getting a Bing Maps Key.

Create a new project

  1. Open Microsoft Visual Studio 2013 and select New Project from the File menu.
  2. In the list of templates, choose Visual C++.
  3. Under the section, choose Store apps.
  4. Under the section, select Universal Apps, Windows apps, or Windows Phone apps (depending on the platform you are targeting), and then select Blank Application.
  5. Name the application BingMapsWithHttpClient and click OK.

Set capabilities to enable network access

Set network capabilities for your app to enable access to the Internet. For this app, you would need to enable network capabilities since the client is connecting to web services.

The Internet (Client) capability is needed since the app needs to be able to connect as a client to a web service on the Internet.

Note  On Windows Phone, there is only one network capability (Internet (Client & Server) which enables all network access for the app.

 

For more information on network access, see How to configure network isolation capabilities.

These steps are needed to set network capabilities for an app before it is deployed if it accesses a web service on the Internet.

  1. Use Visual Studio 2013 to open the package.appxmanifest file.

  2. Select the Capabilities tab.

  3. To build the Windows version of the sample, select the Internet (Client) capability.

    To build the Windows Phone version of the sample, select the Internet (Client & Server) capability.

  4. Save and close the manifest file.

Create the user interface

The user interface consists of two TextBox controls that enable you to enter longitude and latitude values, a TextBlock that displays the location information returned by Bing, and a Button to start the operation. The XAML code below will need to be changed for a Windows Phone Store app.

For a Windows Store app, add the following XAML StackPanel to the grid in MainPage.xaml:

<StackPanel>
    <TextBlock x:Name="TitleText" HorizontalAlignment="Left" Margin="10,10,0,0" 
        TextWrapping="Wrap" Text="Connect to Bing Maps Web Service with the C++ REST SDK" 
        VerticalAlignment="Top" Height="52" Width="1356" FontSize="36"/>
    <StackPanel HorizontalAlignment="Left" Height="204" Margin="20,25,0,0" VerticalAlignment="Top" Width="922">
        <StackPanel Orientation="Horizontal">
            <TextBlock Padding="0,0,10,0" FontSize="14" Text="Enter a valid latitude:" Width="152"></TextBlock>
            <TextBox x:Name="Latitude" TextWrapping="Wrap" Text="47.640194" Height="28" Width="149"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Padding="0,0,10,0" FontSize="14" Text="Enter a valid longitude:"></TextBlock>
            <TextBox x:Name="Longitude"  TextWrapping="Wrap" Text="-122.129865" Height="28.519" 
                UseLayoutRounding="False" Width="149.021" d:LayoutRounding="Auto"/>
        </StackPanel>
        <Button x:Name="LocationButton" Content="Get Location" Height="50" Width="304" Click="Button_Click"/>
        <StackPanel Orientation="Horizontal" Margin="0,20,20,20">
            <TextBlock Padding="0,0,10,10" FontSize="14" Text="Bing Maps Response:"></TextBlock>
            <TextBlock x:Name="BingMapsResponse"  FontSize="14" HorizontalAlignment="Left" TextWrapping="Wrap"  
                VerticalAlignment="Top"  Width="744"/>
        </StackPanel>
    </StackPanel>
</StackPanel>

Add the button handler for LocationButton. An easy way to do this is to delete the existing handler, then start to type it in again, and allow the smart tag to stub out the function for you in MainPage.xaml.h.

Connect to Bing Maps Location API and parse the results

The real work in this sample is all done in our GetLocation method. In this method, we first create a URI to send to the web service that includes the longitude and latitude input values and a query string that specifies that we want the response formatted as JSON and provides the unique key. We then create a new Windows::Web::Http::HttpClient object, which represents an HTTP session. The GetStringAsync method starts an asynchronous GET operation. When that operation completes, we parse the JSON text and write the results into the appropriate TextBlock in our user interface.

Replace all the contents of MainPage.xaml.h with this code:

//
// MainPage.xaml.h
// Declaration of the MainPage class.
//

#pragma once

#include "MainPage.g.h"

namespace BingMapsWithHttpClient
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public ref class MainPage sealed
    {
    public:
        MainPage();

    private:
        void Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
        void GetLocation(Platform::String^ strlong, Platform::String^ strlat);
    };
}

Replace all the contents of MainPage.xaml.cpp with this code:

//
// MainPage.xaml.cpp
// Implementation of the MainPage class.
//

#include "pch.h"
#include "MainPage.xaml.h"
#include <sstream>
// <exception> and <string> are included indirectly via the default
// pch.h header file, which includes ppltasks.h

using namespace concurrency;
using namespace BingMapsWithHttpClient;

using namespace Platform;
using namespace Windows::Data::Json;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Media;
using namespace Windows::UI::Xaml::Navigation;
using namespace Windows::Web::Http;
using namespace std;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/p/?LinkID=234238

MainPage::MainPage()
{
    InitializeComponent();
}

void BingMapsWithHttpClient::MainPage::Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
    GetLocation(Longitude->Text, Latitude->Text);
}

void MainPage::GetLocation(String^ strlong, String^ strlat)
{
    wstring BingServiceKey = L"PASTE YOUR UNIQUE KEY HERE";
    wostringstream fragment;
    fragment << strlat->Data() << ',' << strlong->Data()
        << "?json&key=" << BingServiceKey;
    Uri^ uri = ref new Uri("http://dev.virtualearth.net/REST/v1/Locations/"
        + ref new String(fragment.str().c_str()));

    HttpClient^ httpClient = ref new HttpClient();
    auto op = httpClient->GetStringAsync(uri);
    create_task(op).then([this, strlong, strlat](String^ response)
    {
        wostringstream addressString;
        JsonValue^ val = JsonValue::Parse(response);

        // Display an error message if any of the json objects are not 
        // what we expect.
        try
        {
            auto resourceSets = val->GetObject()->GetNamedArray("resourceSets");
            auto estimatedTotal = resourceSets->GetAt(0)->GetObject()
                ->GetNamedNumber("estimatedTotal");

            if (estimatedTotal == 0)
            {
                return L"BingLocationService: request for " + strlat + ","
                    + strlong + " returned 0 resources";
            }

            auto resources = resourceSets->GetAt(0)->GetObject()->GetNamedArray("resources");
            addressString << "name:  "
                << resources->GetAt(0)->GetObject()->GetNamedString("name")->Data()
                << std::endl << "address:" << endl;

            for (auto& addressPart : resources->GetAt(0)->GetObject()->GetNamedObject("address"))
            {
                addressString << ("    ") << addressPart->Key->Data()
                    << ": " << addressPart->Value->GetString()->Data() << endl;
            }
        }

        catch (Platform::Exception^ e)
        {
            // To show the parse error to the end user
            // may or may not be the right thing to do. This
            // example shows how to capture the error. It is up 
            // to you to use the information appropriately.
            addressString << " Error " << e->Message->Data();
        }

        return ref new String(addressString.str().c_str());

    }).then([this](task<String^> response)
    {
        try
        {
            BingMapsResponse->Text = response.get();
        }

        catch (exception e)
        {
            //Platform::String needs a wchar_t[] for its constructor
            wostringstream wos;
            wos << e.what();
            BingMapsResponse->Text = ref new String(wos.str().c_str());
        }

        catch (Platform::Exception^ e)
        {
            BingMapsResponse->Text = e->Message;
        }
    });
}

The raw JSON response

The snippet below shows the complete response that comes back from Bing Maps web service in response to our HTTP request.

{
   "authenticationResultCode": "ValidCredentials",
   "brandLogoUri": "http://dev.virtualearth.net/Branding/logo_powered_by.png",
   "copyright": "Copyright © 2013 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
   "resourceSets": [
      {
         "estimatedTotal": 1,
         "resources": [
            {
               "__type": "Location:https://schemas.microsoft.com/search/local/ws/rest/v1",
               "bbox": [
                  47.636272,
                  -122.13744,
                  47.643997,
                  -122.12216
               ],
               "name": "Microsoft Way, Redmond, WA 98052",
               "point": {
                  "type": "Point",
                  "coordinates": [
                     47.640137,
                     -122.12981
                  ]
               },
               "address": {
                  "addressLine": "Microsoft Way",
                  "adminDistrict": "WA",
                  "adminDistrict2": "King Co.",
                  "countryRegion": "United States",
                  "formattedAddress": "Microsoft Way, Redmond, WA 98052",
                  "locality": "Redmond",
                  "postalCode": "98052"
               },
               "confidence": "Medium",
               "entityType": "Address",
               "geocodePoints": [
                  {
                     "type": "Point",
                     "coordinates": [
                        47.640137,
                        -122.12981
                     ],
                     "calculationMethod": "Interpolation",
                     "usageTypes": [
                        "Display",
                        "Route"
                     ]
                  }
               ],
               "matchCodes": [
                  "Good"
               ]
            }
         ]
      }
   ],
   "statusCode": 200,
   "statusDescription": "OK",
   "traceId": "0a734b03d01b483b9e3b80216e831cac|BAYM000274|02.00.161.1800|BY2MSNVM000002, BY2MSNVM001076"
}

Other resources

Connecting to web services

Handling exceptions in network apps

How to configure network capabilities

How to connect to an HTTP server using Windows.Web.Http.HttpClient

How to enable loopback and debug network isolation

Reference

Windows::Foundation::Uri

Windows::Web::Http

Windows::Web::Http.Filters

Windows::Web::Http.Headers

Samples

HttpClient Sample