Connecting using XML HTTP Request and IXMLHTTPRequest2 (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]

Use XML HTTP Extended Request and the IXMLHTTPRequest2 interface to send HTTP GET and POST requests to a web service using C++ in a Windows Runtime app.The XML HTTP Request 2 GET sample and XML HTTP Request 2 POST sample demonstrate the features detailed in this topic.

Note  To make HTTP requests in Windows Runtime app developed with C#, Visual Basic, or C++ see Connecting to an HTTP server using Windows.Web.Http.HttpClient.

 

IXMLHTTPRequest2 allows applications to run in a Multi-Threaded Apartment (MTA), a requirement for running under the Windows Runtime in Windows 8. Running in an MTA means that a thread that has access to an IXMLHTTPRequest2 object does not block on request or response processing for other IXMLHTTPRequest2 objects running in the same apartment.

This interface also implements a callback model for event handling. Because IXMLHTTPRequest2 methods allow only asynchronous method calls, to receive completion callbacks an application must pass a pointer to an IXMLHTTPRequest2Callback object when it first calls IXMLHTTPRequest2::Open to create an HTTP request.

For a basic understanding of HTTP request patterns, see RFC 2616.

Prerequisites

The following examples use C++ and are based on he XML HTTP Request 2 GET sample and XML HTTP Request 2 POST 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.

Set capabilities to enable network access

  • Set network capabilities for your app to enable access to a private home or work network and 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 if the app needs to be able to connect as a client to a web services on the Internet. The Private Networks (Client & Server) capability is needed if the app needs to be able to connect as a client to web services on a home network or work network.

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

     

    If an app wants to access the web service running on the same computer as the app, this requires loopback access. An app is normally not allowed loopback access for security reasons. However, apps developed and run in Microsoft Visual Studio 2013 will automatically be registered as being exempt from the loopback restrictions when run in the debugger. For more information, see How to enable loopback and debug network isolation.

    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 or on a private or work network.

  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) and Private Networks (Client & Server) capabilities.

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

  4. Save and close the manifest file.

Create and send a GET request

  1. First create the references required for this operation as well as the callback that indicates request completion. The XML HTTP Request 2 GET sample defines its own implementations of IXMLHTTPRequest2 and IXMLHTTPRequest2Callback, which are used in the creation of the required operational objects in the following examples.

    HRESULT hr = S_OK;
    DWORD dwStatus = 0;
    BOOL fAbort = TRUE;
    ComPtr<IXMLHTTPRequest2> spXHR;
    ComPtr<CXMLHttpRequest2Callback> spXhrCallback;
    
  2. Create and initialize instances of the IXMLHTTPRequest2 and IXMLHTTPRequest2Callback objects.

    //
    // Create and initialize an IXMLHTTPRequest2 object
    //
    hr = CoCreateInstance(CLSID_FreeThreadedXMLHTTP60,
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          IID_PPV_ARGS(&spXHR));
    
    //
    //Create and initialize an IXMLHTTPRequest2Callback object
    //
    hr = MakeAndInitialize<CXMLHttpRequest2Callback>(&spXhrCallback);
    
  3. configure the GET request and send it to the server.

    hr = spXHR->Open(L"GET",              // Method.
                     pcwszUrl,            // Url.
                     spXhrCallback.Get(), // Callback.
                     NULL,                // Username.
                     NULL,                // Password.
                     NULL,                // Proxy username.
                     NULL);               // Proxy password.
    
    //
    //Send the GET request
    //
    hr = spXHR->Send(NULL, 0);
    
  4. Wait for the completion of the request.

    hr = spXhrCallback->WaitForComplete(&dwStatus);
    

    Note  Callers needing to receive completion or status events on a STA or UI thread must use a mechanism that will not block the threads window message pump. One example is by posting a window message to the STA or UI thread window handle.

     

Create and send a POST request

  1. Like the GET example, we first create the references required for this operation as well as the callback that indicates request completion. The XML HTTP Request 2 POST sample also defines its own implementations of IXMLHTTPRequest2 and IXMLHTTPRequest2Callback, which are used in the creation of the required operational objects in the following examples. However, for the POST operation we will need to create the stream used for the operation using XMLHttpRequest2PostStream, an implementation of ISequentialStream defined for the sample. Alternatives to using ISequentialStream for a POST request include SHCreateMemStream/SHCreateStreamOnFile for desktop apps, and CreateStreamOverRandomAccessStream for Windows Runtime apps.

    First create the references required for this operation as well as the callback that indicates request progress. We've also created and defined variables used to represent the size of the file to be sent and indicate request completion.

    HRESULT hr = S_OK;
    DWORD dwStatus = 0;
    ULONGLONG ullFileSize = 0;
    BOOL fAbort = TRUE;
    ComPtr<IXMLHTTPRequest2> spXHR;
    ComPtr<CXMLHttpRequest2Callback> spXhrCallback;
    ComPtr<CXMLHttpRequestPostStream> spXhrPostStream;
    
  2. Create and initialize objects of the IID_IXMLHTTPRequest2, CXMLHTTPRequest2Callback, and XMLHTTPRequestPostStream classes.

    //
    //Initialize IXMLHTTPRequest2Callback
    //
    hr = MakeAndInitialize<CXMLHttpRequest2Callback>(&spXhrCallback);
    if (FAILED(hr))
    {
        goto Exit;
    }
    
    //
    // Create an object of the CXMLHttpRequestPostStream class
    //
    spXhrPostStream = Make<CXMLHttpRequestPostStream>();
    if (spXhrPostStream == NULL)
    {
        hr = E_OUTOFMEMORY;
        goto Exit;
    }
    
  3. Open the file and get the size.

    //
    //Open the file
    //
    hr = spXhrPostStream->Open(pcwszFileName);
    
    //
    //Get file size
    //
    hr = spXhrPostStream->GetSize(&ullFileSize);
    
  4. Prepare the POST request and send it to the server.

    //
    //Configure the POST request
    //
    hr = spXHR->Open(L"POST",             // Method.
                     pcwszUrl,            // Url.
                     spXhrCallback.Get(), // Callback.
                     NULL,                // Username.
                     NULL,                // Password.
                     NULL,                // Proxy username.
                     NULL);               // Proxy password.
    if (FAILED(hr))
    {
        goto Exit;
    }
    
    //
    //Send the POST request
    //
    hr = spXHR->Send(spXhrPostStream.Get(), ullFileSize);
    if (FAILED(hr))
    {
        goto Exit;
    }
    
  5. Wait for the completion of the request.

    hr = spXhrCallback->WaitForComplete(&dwStatus);
    if (FAILED(hr))
    {
        goto Exit;
    }
    
    fAbort = FALSE;
    

    Note  Callers needing to receive completion or status events on a STA or UI thread must use a mechanism that will not block the threads window message pump. One example is by posting a window message to the STA or UI thread window handle.

     

Summary

In this topic we reviewed how to initiate a web service connection with GET and POST requests using XML HTTP Extended Request and the IXMLHTTPRequest2 and IXMLHTTPRequest2Callback interfaces.

Other resources

Connecting to web services

Handling exceptions in network apps

How to configure network capabilities

How to enable loopback and debug network isolation

Reference

XML HTTP Extended Request

IXMLHTTPRequest2

IXMLHTTPRequest2Callback

XML HTTP Extended Request (IXMLHTTPRequest2)

Samples

XML HTTP Request 2 GET sample

XML HTTP Request 2 POST sample