Practical .NET

Calling Web Services with HttpWebRequest, WebClient and HttpClient

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 2 does 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.

About the Author

Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.

comments powered by Disqus
Upcoming Events

.NET Insight

Sign up for our newsletter.

I agree to this site's Privacy Policy.