1. Reveal the HttpClient of the general platform and the httpclient
Original article: Demystifying HttpClient APIs in the Universal Windows Platform
When I was about to translate this article, I found a friend in the garden had already translated it. Now that I have started, I 'd like to translate it again. I will not translate it word by word :). This time is not as busy as before Spring Festival, just sort out the technical documents.
Translation:
As a Universal Windows Platform (UWP) app developer, if you want to interact with the web server through HTTP, you have a lot of APIs to choose from. The two most common and recommended ones are System. Net. Http. HttpClient and Windows. Web. Http. HttpClient. Compared with older webclients and HttpWebRequest (HttpWebRequest can still be used in UWP for backward compatibility), HttpClient is recommended.
We have received some questions about these two APIs, the similarities and differences between their functions, and when to use them. The purpose of these two APIS is described in this article.
Overview
In. NET 4.5, the System. Net. Http. HttpClient API was introduced for the first time and supported by. NET 4.0 and Windows Phone8 Sliverlight apps through the NuGet package. Compared with the old HttpWebRequest, this API aims to provide an HTTP client with a lightweight and scalable abstraction layer. Until Windows8.1, this API is fully implemented at the underlying layer through managed. NET. On Windows 10, this API is implemented in UWP Based on Windows. Web. Http and Windows WinlNet HTTP protocol stacks.
On the other hand, the Windows. Web. Http. HttpClient API was first introduced in Windows 8.1 and Windows phone8.1. The objective is to provide a unified http api support in different Windows app languages (C #, VB, C ++, and JavaScript. Most of the APIs in The namespace of javase. Net. Http are designed and implemented based on Windows D's WinlNet HTTP protocol stack.
Use these APIs in the Windows Store app. The supported system versions and programming languages are as follows:
API |
System Version |
Supported languages |
System. Net. Http. HttpClient |
Windows, Windows Phone8 or above |
Only. NET Language |
Windows. Web. Http. HttpClient |
Windows, Windows Phone8.1 or above |
All Windows Store app languages |
Which one should I use?
The two APIs can be used in UWP. The biggest problem is which one is used in the app. This depends on two factors:
1. Do you need to inherit the original UI to collect user credenui, control HTTP cache read and write, and pass the SSL authentication creden? specified by the client?
If yes, use Windows. Web. Http. HttpClient. So far, this Windows. Web. Http API provides stronger control over Http settings than the System. Net. Http API. In future UWP versions, this System. Net. Http API may support the same features.
2. Do you want to write code across. NET platforms (UWP/ASP. NET 5/iOS and Android )?
If yes, the System. Net. Http API is used. This allows you to write code for other. NET platforms, such as ASP. NET and. NET Framework desktop applications. Based on Xamarin, this API also supports iOS and Android.
Object Model
Now we understand the purpose and principle of these two similar APIs. Let's take a closer look at their object models.
System. Net. Http
The top abstraction is the HttpClient object, which serves as the client entity in the "client-server" Model in the HTTP protocol. This Client can send multiple requests (represented by HttpRequestMessage) to the server, and then receive the corresponding response (represented by HttpResponseMessage ). The entity body and headers of each HTTP request and response are represented by the base class HttpContent, derived classes such as StreamContent, MultipartContent, and StringContent. They indicate different HTTP Entity bodies. They provide some ReadAs * methods to read the Request body or respond to the request as a string, byte array, or stream.
Each HttpClient object has a handler object at the underlying layer that represents all HTTP settings. Theoretically, you can think that handler represents the HTTP protocol stack of the client. It is responsible for sending the HTTP request from the client to the server and transmitting the response back to the client.
The default handler class used in the System. Net. Http API is HttpClientHandler. When you create an HttpClient object-for example, call new HttpClient ()-An HttpClientHandler object is automatically created for your default HTTP protocol stack settings. If you want to change the default settings, such as cache behavior, automatic compression, authentication, and proxy, you can create your own HttpClientHandler entity and change its attributes, then pass it to the HttpClient constructor, for example:
HttpClientHandler myHandler = new HttpClientHandler();myHandler.AllowAutoRedirect = false;HttpClient myClient = new HttpClient(myHandler);
Chaining of Handlers)
A core advantage of the System. Net. Http. HttpClient API design is that it can insert custom handlers and create a chain processing object at the underlying layer of an HttpClient object. For example, your app queries some data from a Web service. You can customize the client logic to handle HTTP 4xx (client errors) and 5xx (server errors), and take specific retry steps, for example, try a different address or add user creden. You want to separate the settings related to the HTTP protocol from the processing logic of the data returned by the web service you are concerned about.
You can create a new handler class (such as CustomHandler1) inherited from DelegatingHandler, and then create an entity to be passed to the HttpClient constructor. The InnerHandler attribute of the DelegatingHandler class is used to specify another handler in the response chain-for example, you can add another Custom handler (such as CustomHandler2 ). For the final handler, you can assign the inner handeler value to an HttpClientHandler entity-this will pass the request to the system's HTTP protocol stack. It looks similar:
Example of implementation logic:
public class CustomHandler1 : DelegatingHandler{ // Constructors and other code here. protected async override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { // Process the HttpRequestMessage object here. Debug.WriteLine("Processing request in Custom Handler 1"); // Once processing is done, call DelegatingHandler.SendAsync to pass it on the // inner handler. HttpResponseMessage response = await base.SendAsync(request, cancellationToken); // Process the incoming HttpResponseMessage object here. Debug.WriteLine("Processing response in Custom Handler 1"); return response; }} public class CustomHandler2 : DelegatingHandler{ // Similar code as CustomHandler1.}public class Foo{ public void CreateHttpClientWithChain() { HttpClientHandler systemHandler = new HttpClientHandler(); CustomHandler1 myHandler1 = new CustomHandler1(); CustomHandler2 myHandler2 = new CustomHandler2(); // Chain the handlers together. myHandler1.InnerHandler = myHandler2; myHandler2.InnerHandler = systemHandler; // Create the client object with the topmost handler in the chain. HttpClient myClient = new HttpClient(myHandler1); }}
Note:
1. If you want to send a request to a remote server, the handler chain is often followed by an HttpClientHandler, which is mainly used to send a request and then receive the OS HTTP protocol stack response. Alternatively, you can use a fake handler to simulate the server and then return a forged response.
2. When sending and receiving requests, add additional processing logic for inner handler, which may cause performance loss. Avoid expensive asynchronous operations.
For more detailed theory about chaining handler, refer to Henrik Nielsen's article. (Note that this is about the ASP. NET Web API version, which may be slightly different from the. NET framework version here, but the chaining handler theory is the same)
Windows. Web. Http
Windows. web. the Http API object model and the System described above. net. the Http Version is similar-it also has a client entity concept, a handler (called "filter" in this namespace "), you can also choose to insert custom logic between the Client object and the system default filter.
Most types of definitions directly simulate the System. Net. Http object model, as shown below:
HTTP client role aspect |
System. Net. Http type |
Corresponding Windows. Web. Http type |
Client entity |
HttpClient |
HttpClient |
HTTP request |
HttpRequestMessage |
HttpRequestMessage |
HTTP response |
HttpResponseMessage |
HttpResponseMessage |
Entity body of an HTTP request or response |
HttpContent |
IHttpContent |
Representations of HTTP content as string/stream/etc. |
StringContent, StreamContent and ByteArrayContent |
HttpStringContent, HttpStreamContent and HttpBufferContent respectively |
HTTP stack/settings |
HttpClientHandler |
HttpBaseProtocolFilter |
Base class/interface for creating custom handlers/filters |
DelegatingHandler |
IHttpFilter |
The System. net. the chaining of handlers discussion of Http is also applicable to Windows. web. http API. Here you can create a custom filters chain and pass them to the HttpClient constructor.
Common HTTP scenarios
Now we can use some code snippets to demonstrate common use cases of two HttpClient APIs. For more information, see the MSDN documentation Windows. Web. Http. HttpClient and System. Net. Http. HttpClient.
Change packet header
System. Net. Http:
If you modify the headers of all requests sent by HttpClient, use the following mode:
var myClient = new HttpClient();myClient.DefaultRequestHeaders.Add("X-HeaderKey", "HeaderValue");myClient.DefaultRequestHeaders.Referrer = new Uri("http://www.contoso.com");
If you only modify the header of the specified request, use:
HttpRequestMessage myrequest = new HttpRequestMessage();myrequest.Headers.Add("X-HeaderKey", "HeaderValue");myrequest.Headers.Referrer = new Uri("http://www.contoso.com");
Windows. Web. Http:
The above mode also applies to Windows. Web. Http APIs.
Note:
1. Some headers are set types. You need to use the Add and Remove methods to edit them.
2. The HttpClient. DefaultRequestHeaders attribute indicates the default settings for headers and will be added to all requests of the app. As this request is processed by the HTTP stack of the operating system, it is added with additional headers before the request is sent.
Timeout settings
System. Net. Http:
In the System. Net. Http API, there are two ways to set timeout. Set timeout for all client requests. Use:
myClient.Timeout = TimeSpan.FromSeconds(30);
Set a request timeout in cancellation token mode:
var cts = new CancellationTokenSource();cts.CancelAfter(TimeSpan.FromSeconds(30)); var httpClient = new HttpClient();var resourceUri = new Uri("http://www.contoso.com"); try{ HttpResponseMessage response = await httpClient.GetAsync(resourceUri, cts.Token);}catch (TaskCanceledException ex){ // Handle request being canceled due to timeout.}catch (HttpRequestException ex){ // Handle other possible exceptions.}
Windows. Web. Http:
The timeout attribute does not exist in the Windows. Web. Http. HttpClient type. Therefore, you must use the preceding cancellation token mode.
Use of authentication creden
System. Net. Http:
To protect user authentication information, the system's HTTP protocol stack does not add certificates for any sent requests by default. To use the certificate of the specified user, use the following mode:
var myClientHandler = new HttpClientHandler();myClientHandler.Credentials = new NetworkCredential(myUsername, myPassword);
Windows. Web. Http:
For Windows. Web. Http APIs, if you need a user certificate when sending a request, a dialog box asking for a user certificate is displayed by default. If you do not want to use this dialog box, set the AllowUI attribute of HttpBaseProtocolFilter to false. You can replace it with the specified certificate:
var myFilter = new HttpBaseProtocolFilter();myFilter.ServerCredential = new PasswordCredential(“fooBar”, myUsername, myPassword);
Note:
1. In the above example, myUsername and myPassword are string-type variables. You can pop up the UI to get user input or get it from app configuration.
2. In the UWP app, The HttpClientHandler. Credentials attribute can only be assigned null, DefaultCredentials, or a NetworkCredential type object.
Use Client certificate
System. Net. Http:
To protect your certificate information, this API does not send any client certificate to the server by default. To use the Client ID card for verification, use:
var myClientHandler = new HttpClientHandler();myClientHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;
Windows. Web. Http:
There are two options to use the client certificate-a UI pops up by default to allow the user to select a certificate. Alternatively, you can set the client certificate by programming, for example:
var myFilter = new HttpBaseProtocolFilter();myFilter.ClientCertificate = myCertificate;
Note:
1. To use the client certificate in two APIs, you must first add it to the store authentication of the app according to these steps. In an app with enterprise capability added, you can also use an existing client certificate in your "My" store.
2. For HttpClientHandler. ClientCertificateOptions, there are two allowed values: Automatic and Manual ). When it is set to Automatic, the most matched client certificate will be selected in the certificate store of the app. When you set it to Manual, it will ensure that no client certificate is sent, even if the server needs it.
Proxy Settings
For the two APIs, the proxy settings use Internet Explorer/Microsoft Edge settings by default, and all HTTP access uses this setting. This enables the app to work automatically even if the user accesses the Internet through a proxy. Neither API provides a method for you to set a custom proxy for the app. However, you can disable the default proxy by setting HttpClientHandler. UserProxy to false (System. Net. Http) or HttpBaseProtocolFilter. UseProxy to false (Windows. Web. Http.
Cookie Processing
By default, for the same app container, both APIs automatically save the cookies returned by the server and add them to the subsequent requests of the URI. Cookies of the corresponding URI can be read and custom cookies can be added. Finally, the two APIs can also disable sending cookies to the server: For System. net. http, set HttpClientHandler. useCookies are false. For Windows. web. http: sets HttpBaseProtocolFilter. cookieUsageBehavior is HttpCookieUsageBehavior. noCookies.
E. Net. Http:
Add a cookie for all requests of the current app:
// Add a cookie manually.myClientHandler.CookieContainer.Add(resourceUri, myCookie);
Add a cookie for the specified request:
HttpRequestMessage myRequest = new HttpRequestMessage();myRequest.Headers.Add("Cookie", "user=foo; key=bar");
For a given URI, check all Cookies:
var cookieCollection = myClientHandler.CookieContainer.GetCookies(resourceUri);
Windows. Web. Http:
Add a cookie for all requests of the current app:
// Add a cookie manually.filter.CookieManager.SetCookie(myCookie);
The preceding method adds a Cookie for the specified request. It is also applicable to Windows. Web. Http APIs.
Manage Cookies:
// Get all cookies for a given URI.var cookieCollection = filter.CookieManager.GetCookies(resourceUri); // Delete a cookie.filter.CookieManager.DeleteCookie(myCookie);
Note:
1. for Windows. web. http APIs are implemented using the WinlNet stack at the underlying layer of some networking APIs in the current application container (app container). Therefore, cookies in cookie manager are shared, such as Windows. web. syndication, Windows. web. atomPub, XHR, etc. Therefore, for requests from the same server, a cookie received from the server through the Syndication API may be added to the subsequent HttpClient request.
Maximum number of connections per server
By default, the underlying HTTP protocol stack of the operating system can use up to six HTTP connections for each server. The HttpClient API of System. Net. Http does not provide the control method. For Windows. Web. Http APIs, you can use:
var myFilter = new HttpBaseProtocolFilter();myFilter.MaxConnectionsPerServer = 15;
Recent updates
In Windows 10On the UWP app, we added HTTP/2 support for both APIs.. This feature is enabled by default, so developers can get some benefits without changing the Code, such as lower latency. For both APIs (System. Net. Http and Windows. Web. Http), you can disable this feature and use HTTP 1.1 or 1.0.
For the future, we plan to add more popular features, such as custom server SSL certificate verification and support for handlers/filters added to HttpClient created elsewhere. To write better Windows apps, we look forward to your feedback on the new features required by these Apis. You can propose an idea at UserVoice, or you 'd better join Windows Insiders program and submit Feedback through the Forum or Windows Feedback app.
This article is written by Sidharth Nabar, the project manager of Windows Networking APIs team.