A first hand look from the .NET engineering teams
Three months ago we shipped the first preview of the portable HttpClient. Many of you wondered when we would ship the RTM version. Today, we’re happy to announce the first step towards an RTM: We shipped a release candidate (RC) of HttpClient (Microsoft.Net.Http package on NuGet) that includes all the bug fixes since the preview.
To address some of the platform differences in a portable fashion, we’ve added new capability APIs.
HttpClientHandler.SupportsUseProxy(): The existing HttpClientHandler.SupportsProxy property indicates whether both the UseProxy property and the Proxy property are supported. This created an issue because some platforms (for example, Windows Phone) don’t allow you to configure a proxy explicitly. However, Windows Phone lets you control whether the machine wide proxy should be used. To model this behavior, we added the HttpClientHandler.SupportsUseProxy() extension method. For some platforms that don’t support both, such as Windows Phone, the SupportsProxy property will continue to return false, but the SupportsUseProxy() method will return true.
HttpClientHandler.SupportsAllowAutoRedirect(): The HttpClientHandler.SupportsRedirectConfiguration property had a similar issue: It controls whether both the AllowAutoRedirect and the MaxAutomaticRedirections properties are supported. Windows Phone doesn’t support specifying the maximum number of automatic redirections, but it does support redirection. For that reason, we added the HttpClientHandler.SupportsAllowAutoRedirect() extension method.
Here's how you use these capability APIs:
HttpClientHandler handler = new HttpClientHandler();
// Configure proxy (if supported)
handler.UseProxy = true;
// Allow automatic redirection (if supported)
handler.AllowAutoRedirect = true;
In case you are wondering why we added extension methods instead of regular properties: Some of the platforms that Microsoft.Net.Http supports already provide the HttpClientHandler class, which is used on those platforms. Since we can’t modify the built-in version of the properties directly, we added extension methods that ship in a separate assembly with the NuGet package.
All bug fixes are listed in the release notes. In this post, I’d like to highlight just one:
Issue: When consuming a portable class library that depends on HttpClient from a Windows Store application, the app can crash with a MissingMethodException.
We’ve fixed this bug by using the technique we explained in our blog post about Microsoft.Bcl.Async: We ensure during the build that the application has a reference to the NuGet package.
This RC doesn’t include support for the HttpClientHandler.AutomaticDecompression property. Many of you have asked for this support, and we certainly haven’t ignored it or forgotten about it. In fact, our original plan was to ship another preview with support for automatic decompression, and then ship an RTM version a few weeks later. So why did we change our minds about it?
We had two options:
We decided to go with the second option, because we believe it delivers functionality sooner to our customers. After all, that's why we ship on NuGet, and we hope you agree.
Let’s recap why our team is investing so much in releasing components via NuGet. The reason is twofold:
First, it allows bridging differences in functionality between platforms we already shipped. A good example is HttpClient, and also includes the support for the async and await keywords. Shipping features out of band also enables us to ship new functionality for multiple platforms via a single portable class library, without having to wait for any of the platforms to add that functionality.
Second, our goal is to strengthen the feedback loop with you, our customers. In the past, we’ve shipped “big” betas, like a beta of the entire .NET Framework. This approach certainly has some advantages, but we’ve seen issues with it as well. The biggest downside is that “big” betas are pretty expensive to ship and are typically very close to RTM, which, in turn, means that we can’t make impactful changes anymore. In fact, we have to turn down a large number of the bug reports we get in “big” betas, either because they affect a relatively small number of customers or because fixing the bugs would place the RTM release at risk. We’re certainly not the first company running into this problem; there is an entire agile software development movement in our industry that focuses on this. I don’t want to go into a philosophical discussion about agile methodologies, but it’s pretty hard to disagree that shipping early and often helps with feedback loop issues.
A good example where we use your feedback quite heavily is in the previews of immutable collections; in contrast to “big” betas, we were able to change the design of the APIs when we believe that’s the correct approach.
Unfortunately, shipping a constant stream of previews isn’t necessarily a helpful solution in all scenarios. On certain platforms, such as the .NET Framework 4.5 and Windows Store, HttpClient is already available as a fully supported, RTM-quality component. For that reason, we can offer a preview of HttpClient only for Windows Phone today.
Here are our tentative plans for future NuGet releases of HttpClient:
We released an RC version of the Microsoft.Net.Http NuGet package. We expect this to be the last preview of HttpClient before we ship an RTM. Please provide feedback if you find any issues.
Of course, we’d also love to hear from you if everything just works. After all, we're happy if you're happy!
I'm getting a NotImplementedException when trying to use WebRequestHandler's ServerCertificateValidationCallback. Has it been implemented in this package yet? Are there plans for it?
Thanks for the update. Looks like GetStreamAsync is also broken. Whilst trying to download a file, I get NotSupportedException: Read is not support on the main thread while buffering is disabled.
On second thoughts, I changed CopyTo to CopyToAsync and it works now. Sorry for complaining.
@Morten & @HermitDave: This change as intentional. We enabled the streaming scenario by turning off AllowReadStreamBuffering on our underlying HttpWebRequest. HttpClient defines a set of APIs that let you more granularly control the buffering behavior (HttpCompletionOption & HttpResponseMessae.ReadAs*Async & LoadIntoBufferAsync). It was a bug in Beta that setting HttpCompletionOption.ResponseHeadersRead had no effect (because we were telling phone to buffer the entire request), now that it is fixed it exposes this problem. For folks that run into this you can either pass in HttpCompletionOption.ResponseContentRead when you make the request or await response.Content.LoadIntoBufferAsync().
@Alexander: HttpClient is really just a wrapper on top of HttpWebrequest. HttpWebRequest on phone does not support Proxy and we haven't done the work to emulate it. The right thing to do here would be to add support to the phone platform if it's needed. If this is something you'd like I reccomend upvoting wpdev.uservoice.com/.../1712457-authenticated-proxy-support-in-code-httpwebreques.
@Jose: Phone's error reporting isn't great, a lot of things are remapped to 404. Take a look at a network trace to find out what is causing the failure.
@Nate: ServerCertificateValidationCallback relies on HttpWebRequest.ServerCertificateValidationCallback which is not present in .Net 4.0. You'll need to target .Net 4.5 if you want to use it.
I added some logs on the server and i saw that the phone sends about 200-300kb before failing.
The same server is used to send pictures in other platforms without any problems.
Do you think that the problema could be the headers?.
httpclient on WP8 under low connectivity (2G) gives me a lot of problems, is there any way to increase the waiting time? It gives me 404 error (I know that this error is not very descriptive) really fast. I tried to use a Windows Phone Component in C++ with the same results.
Found a bug in GetStreamAsync. When running under the debugger I am getting this exception: "'iso-8859-1' is not a supported encoding name.", which I cannot continue from.
If I disable the "Break when exception is thrown" setting then my application works correctly. But of course that really screws up my ability to debug.