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

Featured

  • Compare New GitHub Copilot Free Plan for Visual Studio/VS Code to Paid Plans

    The free plan restricts the number of completions, chat requests and access to AI models, being suitable for occasional users and small projects.

  • Diving Deep into .NET MAUI

    Ever since someone figured out that fiddling bits results in source code, developers have sought one codebase for all types of apps on all platforms, with Microsoft's latest attempt to further that effort being .NET MAUI.

  • Copilot AI Boosts Abound in New VS Code v1.96

    Microsoft improved on its new "Copilot Edit" functionality in the latest release of Visual Studio Code, v1.96, its open-source based code editor that has become the most popular in the world according to many surveys.

  • AdaBoost Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the AdaBoost.R2 algorithm for regression problems (where the goal is to predict a single numeric value). The implementation follows the original source research paper closely, so you can use it as a guide for customization for specific scenarios.

  • Versioning and Documenting ASP.NET Core Services

    Building an API with ASP.NET Core is only half the job. If your API is going to live more than one release cycle, you're going to need to version it. If you have other people building clients for it, you're going to need to document it.

Subscribe on YouTube