Sdílet prostřednictvím


How to connect to an HTTP server using Windows.Web.Http (HTML)

[ 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 ]

Send a GET request to a web service and retrieve the response using the Windows.Web.Http.HttpClient class in the Windows.Web.Http namespace.

[Get the HTTPClient sample now.]

Classes in the Windows.Web.Http namespace provide a programming interface for modern HTTP client apps. The Windows.Web.Http namespace and the related Windows.Web.Http.Headers and Windows.Web.Http.Filters namespaces provide HTTP client components that allow users to make HTTP requests and receive HTTP responses from modern web services over HTTP.

Windows 8.1 introduces Windows.Web.Http, the Windows Runtime namespace to use for Windows apps that connect to HTTP and Representational State Transfer (REST) web services. This new API provides full feature support across all supported languages, and replaces the HTTP API originally released for Windows 8 .

This new API replaces the use of three different APIs with differing features that previously were needed for each language projection in Windows 8.

For basic request operations, the new API has a simple interface to handle the most common tasks and provides sensible defaults for authentication (AUTH) that apply to most scenarios. For more complex HTTP operations, additional capabilities include.

  • Methods for common verbs (DELETE, GET, PUT, and POST)

  • Support for common authentication settings and patterns

  • Access to Secure Sockets Layer (SSL) details on the transport

  • Ability to include customized filters in advanced apps

  • Ability to get, set, and delete cookies

  • HTTP Request progress info available on asynchronous methods

The Windows.Web.Http.HttpClient class is used to send and receive basic requests over HTTP. It provides the main class for sending HTTP requests and receiving HTTP responses from a resource identified by a URI. This class can be used to send a GET, PUT, POST, DELETE, and other requests to a web service. Each of these requests is sent as an asynchronous operation.

The Windows.Web.Http.HttpRequestMessage class represents an HTTP request message sent by Windows.Web.Http.HttpClient. The Windows.Web.Http.HttpResponseMessage class represents an HTTP response message received from an HTTP request. HTTP messages are defined in RFC 2616 by the IETF.

The Windows.Web.Http namespace provides a number of different classes that represent HTTP content (the HTTP entity body and content headers including cookies) associated with an HTTP request or an HTTP response. These different classes allow content to use a buffer, a string, a stream, as well as name/value data encoded with the application/x-www-form-urlencoded MIME type, multipart/* MIME type, and multipart/form-data MIME type. Also custom content can be defined.

In this example, the HttpStringContent class is used to represent the HTTP response as a string.

The Windows.Web.Http.Headers namespace supports creation of HTTP headers and cookies, which are then associated as properties with HttpRequestMessage and HttpResponseMessage objects.

Prerequisites

The following examples in this topic are provided in JavaScript and HTML. A basic understanding of HTTP requests as detailed in RFC 2616 is required.

It is also possible to make HTTP requests in an app using JavaScript and HTML using WinJS.xhr and XMLHttpRequest. For more information, see Connecting to a web service (Windows Runtime app using JavaScript).

Instructions

Step 1: 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 JavaScript.
  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 HttpClientGet and click OK.

Step 2: Set capabilities to enable network access

You need to 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.

For an app using Windows.Web.Http.HttpClient to connect to a web service on a different computer, the app would need network capabilities set. If the app needs to be able to connect as a client to a web services on the Internet, then the Internet (Client) 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, then the Private Networks (Client & Server) capability is needed.

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

 

If the web service is running on the same computer as the app, this would require loopback access. Apps developed and run in Visual Studio 2013 will automatically be registered as being exempt from the loopback restrictions. For more information, see How to enable loopback and debug network isolation.

For more information on network access, see How to configure network 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.

Step 3: Add HTML UI

  • In this section, we define the app layout in HTML to specify the approximate size and position of each object in the app. We complete the UI for the app by adding controls and content to display data.

    This sample uses simple HTML UI elements that include the following:

    • A control with class used for a text label and the input field for the input URI address and a button used to start the asynchronous request.

    • A control with a class with a text label and a text field to display the current status. This is where status and error messages will be displayed. This control also contains a class where the output received from the web service is displayed. In this sample, the result of the HTTP GET operation is displayed as plain text containing HTML markup.

    Open the js folder and open the existing default.js file and add the following UI elements to this file.

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>HttpClientGet</title>
    
        <!-- WinJS references - Windows -->
        <link href="//Microsoft.WinJS.2.0/css/ui-dark.css" rel="stylesheet" />
        <script src="//Microsoft.WinJS.2.0/js/base.js"></script>
        <script src="//Microsoft.WinJS.2.0/js/ui.js"></script>
    
        <!-- WinJS references - Phone -->
        <link href="/css/ui-themed.css" rel="stylesheet" />
        <script src="//Microsoft.Phone.WinJS.2.1/js/base.js"></script>
        <script src="//Microsoft.Phone.WinJS.2.1/js/ui.js"></script>
    
        <!-- HttpClientGet references -->
        <link href="/css/default.css" rel="stylesheet" />
        <script src="/js/default.js"></script>
        <script src="/js/mainpage.js"></script>
    </head>
    
    <body>
        <div data-win-control="SampleInput">
            <p> Download the contents of a page and display it. </p>
            <p class="clear">
                <label for="inputAddress">URI Address:</label>
                <input type="text" id="inputAddress" value="https://www.contoso.com" />
            </p>
            <p>
                <button id="startButton">Start</button>
            </p>
        </div>
        <div data-win-control="SampleOutput">
            <p class="clear">
                <label for="statusText">Status:</label>
                <input type="text" id="statusText" value="" />
            </p>
            <textarea id="outputView"></textarea>
        </div>
    </body>
    </html>
    

Step 4: Create the HttpClient

  • First create the Windows.Web.Http.HttpClient object and add a user-agent header.

    By default, no user-agent header is sent with the HTTP request to the web service by the HttpClient object. Some HTTP servers, including some Microsoft web servers, require that a user-agent header be included with the HTTP request sent from the client. The HTTP server returns an error if no header is present. We need to add a user-agent header using classes in the Windows.Web.Http.Headers namespace. We add this header to the HttpClient.DefaultRequestHeaders property to avoid these errors.

    Open the js folder and add a new mainpage.js file and add the following code to the file.

    (function () {
        "use strict";
    
        var httpClient;
        var httpPromise;
    
        var page = WinJS.UI.Pages.define("/html/mainpage.html", {
            ready: function (element, options) {
                document.getElementById("startButton").addEventListener("click", start, false);
    
                httpClient = new Windows.Web.Http.HttpClient();
    
                // Add a user-agent header
                headers = httpClient.defaultRequestHeaders;
    
                // UserAgent is a HttpProductInfoHeaderValueCollection
                // A collection of HttpProductInfoHeaderValue items
    
                // The safe way to check a header value from the user is the TryParseAdd method
                // Since we know this header is okay, we use ParseAdd with will throw an exception
                // with a bad value 
    
                headers.userAgent.parseAdd("ie");
                headers.userAgent.parseAdd("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
            }
        });
    })();
    

    Open the js folder and the default.js file and add the following code to the file.

    (// For an introduction to the Blank template, see the following documentation:
    // https://go.microsoft.com/fwlink/p/?LinkID=232509
    (function () {
        "use strict";
    
        var app = WinJS.Application;
        var activation = Windows.ApplicationModel.Activation;
    
        app.onactivated = function (args) {
            if (args.detail.kind === activation.ActivationKind.launch) {
                if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                    startButton.onclick = start;
    
                } else {
                    startButton.onclick = start;
                }
                args.setPromise(WinJS.UI.processAll());
            }
        };
    
        app.oncheckpoint = function (args) {
            // This application is about to be suspended. Save any state
            // that needs to persist across suspensions here. You might use the
            // WinJS.Application.sessionState object, which is automatically
            // saved and restored across suspension. If you need to complete an
            // asynchronous operation before your application is suspended, call
            // args.setPromise().
        };
    
        app.start();
    })();
    

Step 5: Send the GET request and receive the response

  • When the Start button is clicked, we first validate that the URI specified in the inputAddress is valid. Then we send the GET request using the URI and wait to receive the response from the HTTP server.

    Most of the work is done in the click handler for the Start Button. When this button is clicked, the text in the statusText and outputView UI elements is updated. The input URI address is first checked to make sure that the user passed a valid URI address. If we have a valid URI from the user, then the app sends the HTTP GET request to the specified URI and waits for the HTTP response. If an error or exception occurs, the result is displayed in the statusText UI element. If no errors occur, the response from the web service is displayed in the outputView UI element.

    An exception is thrown when an invalid string for the Uniform Resource Identifier (URI) is passed to the constructor for the Windows.Foundation.Uri object.

    In JavaScript, there is no method to try and parse a string to a URI. To catch this exception in that case, use a try/catch block around the code where the URI is constructed.

    The sample also checks that the HTTP scheme in the URI is HTTP or HTTPS since these are the only schemes supported by the Windows.Web.Http.HttpClient.

    Using the then and done keywords in JavaScript, the code for sending the GET request and retrieving the response asynchronously is similar to the code we would use to complete this operation synchronously.

    Exceptions from network errors (loss of connectivity, connection failures, and HTTP server failures, for example) can happen at any time. These errors result in exceptions being thrown. If not handled by your app, an exception can cause your entire app to be terminated by the runtime. You must write code to handle exceptions when you call most asynchronous network methods. Sometimes when an exception occurs, a network method can be retried to try and resolve the problem. Other times, your app may need to plan to continue without network connectivity using previously cached data. For more information on handling network exceptions, see Handling exceptions in network apps.

    The HttpResponse.EnsureSuccessStatusCode method throws an exception if the web server returned an HTTP error status code, an HttpResponse.StatusCode not in the Successful range (200-299) for the request. We use a try/catch block for any exceptions and print out the exception message in the statusText UI element if an error occurs.

    The HttpResponse.Content property represents the content of the HTTP response. The HttpClient.GetAsync(Uri) method reads the HTTP content to a string as an asynchronous operation. We replace any <br> tags in the returned HTML text as newlines for display purposes. If the method is successful, we display the HttpResponse.StatusCode in the statusText UI element and HttpResponse.Content returned by the web service in the outputView UI element.

    Open the js folder and add the following code to the mainpage.js file.

        function start()
        {
    
            var response = new Windows.Web.Http.HttpResponseMessage();
    
            var statusText = document.getElementById("statusText");
            var outputView = document.getElementById("outputView");
    
            // The value of 'inputAddress' is set by the user 
            // and is therefore untrusted input. 
            // If we can't create a valid absolute URI, 
            // We notify the user about the incorrect input.
    
            statusText.Text = "Testing URI is valid.";
    
            var uriString = document.getElementById("inputAddress").value.trim();
            if (!uriString) {
                return;
            }
    
            var resourceUri;
            try {
               resourceUri = new Windows.Foundation.Uri(uriString);
            }
            catch (Exception) {
                statusText.Text = "Invalid URI, please re-enter a valid URI.";
                return;
            }
    
            if (resourceUri.schemeName != "http" && resourceUri.schemeName != "https") {
                statusText.Text = "Only 'http' and 'https' schemes supported. Please re-enter URI";
                return;
            }
    
            var responseBodyAsText="";
            outputView.Text = "";
            statusText.Text = "Waiting for response ...";
    
            httpPromise = httpClient.getAsync(resourceUri).then(function (response) {
                outputStatus = response.statusCode + " " + response.reasonPhrase;
    
                response.EnsureSuccessStatusCode();
    
                response.content.readAsStringAsync().then(function (responseBodyAsText) {
                // Format the HTTP response to display better
                responseBodyAsText = responseBodyAsText.replace(/<br>/g, "\r\n");
                outputView.value = responseBodyAsText;
                return response;
            });
        )};
    
        httpPromise.done(function (response) {
            statusText.value = response.StatusCode + " " + response.ReasonPhrase + "\r\n";
        }, onError);
    
        function onError(error) {
            statusText.value = "Error = " + error.number + "  Message: " + error.message;
        }
    
    })();
    

    Windows.Web.Http.HttpClient uses WinInet to send HTTP and web service requests and receive responses. The default timeout value used by WinInet for an HTTP connect operation is 60 seconds. If an HTTP server or web service is temporarily down or blocked by a firewall and the server doesn't or can't respond to the Windows.Web.Http.HttpClient request, WinInet waits the default 60 seconds before it returns an error which causes an exception to be thrown in the app. If the name query for an HTTP server name returns multiple IP addresses for the name, WinInet tries a number of the other IP addresses for the site each with a default timeout of 60 seconds before it fails. An app making an HTTP or web service request could wait several minutes making retries for multiple IP addresses, before an error is returned by WinInet and an exception is thrown. This behavior could appear to the user as if the app stopped working. The default timeout used by WinInet for send and receive operations after a connection has been established is 30 seconds.

    To make the app more responsive and minimize these issues, an app could be enhanced by setting a shorter timeout on Windows.Web.Http.HttpClient operations so that operations fail sooner from the timeout rather than from the default WinInet settings. For more information on how to setup a timeout, see Setting timeout values with WinJS.xhr or HttpClient and How to set timeouts on socket operations.

Remarks

In this topic we reviewed how to use the Windows.Web.Http.HttpClient class to send a GET request to a web service and retrieve the response using the Windows.Web.Http.HttpResponseMessage and related classes in the Windows.Web.Http.Headers namespace.

Other resources

Connecting to web services

Handling exceptions in network apps

How to configure network capabilities

How to enable loopback and debug network isolation

Setting timeout values with WinJS.xhr or HttpClient

Reference

Windows.Foundation.Uri

Windows.Web.Http

Windows.Web.Http.Filters

Windows.Web.Http.Headers

Samples

HttpClient Sample

Web authentication sample