Calling Web Services with HttpWebRequest, WebClient and HttpClient
Ref. https://visualstudiomagazine.com/articles/2017/06/01/calling-web-services.aspx
The .NET Framework gives you three different ways to call a Web Service. However, depending on your scenario, the latest and greatest object isn’t necessarily your best choice.
If you’re going to call a RESTful Web Service, the .NET Framework gives you three objects you can use to make the call: HttpWebRequest, WebClient and HttpClient. Each has its costs and benefits (of course), so this column is about why you might choose each one.
HttpWebRequest: Full Control
For me, the HttpWebRequest is primarily of "historical interest" -- it’s the earliest of the tools to appear (as I remember) and is also the least "developer-friendly" of the three objects.
The issue with the HttpWebRequest is that, if you want to call a RESTful service with the HttpWebRequest, you’re going to have to specify everything yourself. Listing 1 shows the simplest possible request using the HttpWebRequest object: a call to a single Web Service method, passing a single parameter ("Vogel"), and getting back a single, Boolean result.
Listing 1: Calling a RESTful Service Using HttpWebRequest
Dim hwr As HttpWebRequest hwr = WebRequest.Create("http://localhost:56590/Home/ValidName?LastName=Vogel") Try Dim wr As WebResponse wr = hwr.GetResponse() If CType(wr, HttpWebResponse).StatusCode = HttpStatusCode.OK Then Dim st As Stream st = wr.GetResponseStream() Dim sr As StreamReader sr = New StreamReader(st) Dim res As Boolean res = sr.ReadToEnd() If res Then '...work with result... End If End If Catch ex as Exception '...handle error... End Try
I’ve left some important steps out of here: I haven’t, for example, provided any credentials to log into the service; in C# the conversion of the returned data (the string "false") to a Boolean would be more complicated; and the WebResponse has a Dispose method that I should be calling through a Using block. But, even with those steps omitted, that’s a lot of code.
What’s good about the HttpWebRequest is that you have complete control over everything that’s sent to the Web Service. You can set the user agent string to allow your client to, for example, masquerade as an iPhone.
WebClient: Ease of Use
The WebClient object addresses the complexity of the HttpWebRequest by wrapping it to provide a simpler interface for calling RESTful services. Listing 2does the same thing as Listing 1, but requires far less code.
Listing 2: Calling a RESTful Service Using WebClient
Dim wc As WebClient wc = New WebClient Try Dim res As Boolean res = wc.DownloadString("http://localhost:56590/Home/ValidName?LastName=Vogel") If res Then '...work with result... End If Catch ex As Exception '...handle error... End Try
In addition to simplifying requests, the WebClient provides methods for asynchronously calling Web Services (both in uploading and downloading). And, while you don’t have quite the low-level control that the HttpWebRequest does, it still gives you (for example) the ability to manipulate the headers that you send to the Web Service.
If you’re using a version of the .NET Framework earlier than 4.5, then the WebClient should be your first choice. You should use the HttpWebRequest only if you find there’s something you need that the WebClient won’t do.
HttpClient: Asynchronous Heaven
However, if you are using the .NET Framework version 4.5 or later (and version 4.5 has been out for five years now), then you also have access to the HttpClient object. The HttpClient provides functionality that neither WebClient nor HttpWebRequest does. For example, with HttpClient you can make multiple requests without having to create a new object; you can track the progress of long-running requests; and it’s a lot easier to integrate the HttpClient into testing through mocking.
The downside of using the HttpClient is that every method is asynchronous. If you use HttpClient in a pseudo-synchronous mode, the code can be a little ugly, as Listing 3 shows, which has almost as many lines of code as the original HttpWebRequest object required.
Listing 3: Calling a RESTful Service Using HttpClient Synchronously
Dim hc As HttpClient hc = New HttpClient Try Dim trm As Task(Of HttpResponseMessage) trm = hc.GetAsync("http://localhost:56590/Home/ValidName?LastName=Vogel") Dim rm As HttpResponseMessage rm = trm.Result If rm.IsSuccessStatusCode Then Dim ts As Task(Of String) ts = rm.Content.ReadAsStringAsync Dim res As Boolean res = ts.Result If res Then '...work with result... End If End If Catch ex As Exception '...handle exception... End Try
However, if you use HttpClient as it was intended (asynchronously), then the code gets simpler. If I use await and async, as shown in Listing 4, the code isn’t quite as short as with the WebClient … but it’s close and it’s asynchronous.
Listing 4: Calling a RESTful Service Using HttpClient Asynchronously
Dim hc As HttpClient hc = New HttpClient Try Dim rm As HttpResponseMessage rm = Await hc.GetAsync("http://localhost:56590/Home/ValidName?LastName=Vogel") If rm.IsSuccessStatusCode Then Dim res As Boolean res = Await rm.Content.ReadAsStringAsync If res Then '...work with a result... End If End If Catch ex As Exception '...work with exception... End Try
So what is my best choice? If I’m happy with synchronous code and don’t need to mock my RESTful calls when testing, I’m still using the WebClient. However, if I can leverage asynchronous code, have a long-running process I want to track, or need to mock calls for testing, then I use HttpClient. And, on those very rare occasions when I need to do something odd with the HTTP protocol, I fall back on the HttpWebRequest object.
You can’t, after all, have too many tools.