Querying Bing Using the New Windows 7 Web Services C++ API

Introduction

According to MSDN, WWSAPI is a native-code implementation of SOAP which provides core network communication functionality by supporting a set of the WS-* and .NET-* family of protocols. WWSAPI is designed to be used by components/applications which fall into one of the following categories:

  • Native code mandate
  • Require minimal dependencies
  • Require minimal startup time
  • Memory constrained environments

Using this brand new API, it is possible to make native-code SOAP based web services and clients for SOAP based web services. This article will explain how to build client applications that use SOAP based web services. The web service that will be used in the examples is the Microsoft Bing SOAP API which allows you to search for text, images and so on. You will need to have the Windows 7 SDK installed to follow the steps in this article. Get the SDK. Code using the WWSAPI will run out-of-the-box on Windows 7 and Windows Server 2008 R2. If you want to run it on Windows XP, Windows Vista, Windows Server 2003 or Windows Server 2008, you need to install a redistributable. Unfortunately, it’s impossible to get this redistributable at the time of this writing except by getting a Microsoft Services Partner Advantage agreement, which is quite expensive.

More information about the Windows Web Services API can be found at http://msdn.microsoft.com/en-us/library/dd430435(VS.85).aspx

The Bing API

Before you can start using the Bing API, you need to get your Bing API AppID. Get one now. Once you have your AppID, which you will need in your C++ code, you can download the Bing SDK from here. This SDK contains some documentation on the SOAP Bing API and it includes the SOAP WSDL file which we will need for our examples.

The Console Bing Text Search Application

Let’s start with a simple console application that will allow you to search for a specific string on www.bing.com. The following steps are necessary:

  1. Start Visual Studio.
  2. Create a new Console application using the project wizard.
  3. Copy the search.wsdl which was installed by the Bing SDK to your source folder of your new console application. If you used the default installation folder during the Bing SDK setup, the search.wsdl file will be located in the following folder “My DocumentsBing API 2.0 SDKSamplesCSharpSOAPWeb Referencesnet.bing.api”.
  4. Open a Visual Studio command line window. You should be able to find a shortcut to this in your start menu under “Microsoft Visual Studio > Visual Studio Tools > Visual Studio Command Prompt”.
  5. Navigate to the folder containing the source code for your new console application.
  6. Run the following command:
  7. wsutil search.wsdl
  8. This command will generate 2 files search.wsdl.c and search.wsdl.h which are proxy files that we will use in our code.
  9. Close the command line.
  10. In Visual Studio, add the search.wsdl, search.wsdl.c and search.wsdl.h files to your console project.
  11. Right click on the search.wsdl.c file, select “Properties”, go to “C/C++ > Precompiled Headers” and set “Precompiled Header” to “Not Using Precompiled Headers”.

Initializing the WWSAPI

Now we are ready to start writing our WWSAPI code. All WWSAPI code will be encapsulated in a CBingSearchService class. The first thing this class will need to do is initialize the WWSAPI. This can be done as follows:

  void CBingSearchService::Initialize()
  {
      // If Initialize was called multiple times, make sure
      // to cleanup first.
      Cleanup();

      // Create an error object
      HRESULT hr = WsCreateError(NULL, 0, &m_error);
      if (FAILED(hr))
      {
          ShowError(hr);
          return;
      }

      // Create a heap to store deserialized data
      hr = WsCreateHeap(2048000, 512, NULL, 0, &m_heap, m_error);
      if (FAILED(hr))
      {
          ShowError(hr);
          return;
      }

      WS_CHANNEL_PROPERTY channelProperties[2]; // hold up to 2 channel properties
      ULONG channelPropertyCount = 0;

      WS_ENVELOPE_VERSION soapVersion = WS_ENVELOPE_VERSION_SOAP_1_1;
      channelProperties[channelPropertyCount].id = WS_CHANNEL_PROPERTY_ENVELOPE_VERSION;
      channelProperties[channelPropertyCount].value = &soapVersion;
      channelProperties[channelPropertyCount].valueSize = sizeof(soapVersion);
      channelPropertyCount++;

      WS_ADDRESSING_VERSION addressingVersion = WS_ADDRESSING_VERSION_TRANSPORT;
      channelProperties[channelPropertyCount].id = WS_CHANNEL_PROPERTY_ADDRESSING_VERSION;
      channelProperties[channelPropertyCount].value = &addressingVersion ;
      channelProperties[channelPropertyCount].valueSize = sizeof(addressingVersion);
      channelPropertyCount++;

      // Create the proxy
      hr = WsCreateServiceProxy(WS_CHANNEL_TYPE_REQUEST, WS_HTTP_CHANNEL_BINDING,
          NULL, NULL, 0, channelProperties, channelPropertyCount, &m_proxy, m_error);
      if (FAILED(hr))
          ShowError(hr);
      else
          m_bInitialized = true;
  }

This function first creates a WS_ERROR object. This object is passed to all WWSAPI functions and allows us to get detailed error messages when something goes wrong. After this, a heap is created that the WWSAPI will use for all its memory management. The last thing this function does is setting up the service proxy. For this we need to configure two channel properties, specifying the envelope version of the SOAP protocol used by the web service (Bing in this example) and the addressing version used for the transport of data between the client and the web service. Both of these pieces of information depend on the target SOAP server that you want to use. That’s all the initialization that is necessary to get started.

Connecting to the Bing Servers

The next thing the class needs to do is to actually connect to the remote web service endpoint. This is handled by the following function:

  void CBingSearchService::Connect()
  {
      if (!m_bInitialized)
          Initialize();

      WS_ENDPOINT_ADDRESS address = {};
      WS_STRING url = WS_STRING_VALUE(L"http://api.bing.net/soap.asmx");
      address.url = url;

      // Opens the connection to the service endpoint.
      HRESULT hr = WsOpenServiceProxy(m_proxy, &address, NULL, m_error);
      if (FAILED(hr))
          ShowError(hr);
      else
          m_bConnected = true;
  }

It first checks whether the WWSAPI is initialized and if not will call our earlier function to initialize it. After this, it sets up a WS_ENDPOINT_ADDRESS that contains the URL of the endpoint of our web service and then calls WsOpenServiceProxy to make the connection with the remote server.

More by Author

Must Read