HttpWebRequest
The HttpWebRequest class is interesting in that until very recently, it was the workhorse class of network programming in .NET. This is evident in the huge explosion of the class specification when compared to the relative simplicity of the WebRequest class. There are properties for each standard HTTP header that could be defined for a given payload, as well as a headers property inherited from the base class for specifying custom or non-standard headers. There are properties to specify the transport details, such as the TransferEncoding, or whether or not to send data in chunked segments. There are properties to specify how to handle exceptional behaviors from the remote host, such as the MaximumResponseHeadersLength and MaximumAutomaticRedirections properties. All of these properties allowed you to build a complete and strong payload for an HTTP request from scratch. As you can imagine, though, it was often tedious, error-prone, and verbose to do this for every request to every HTTP resource. Often, developers would hand-roll custom HTTP client classes of their own to isolate that aspect of their application in a write once, use everywhere approach. This degree of granularity is why the engineers at Microsoft decided to write a more robust and easy-to-use client for brokering common HTTP requests.
It is interesting to note, however, that if you look at class specifications side by side, the method signatures exposed by HttpWebRequest are exactly the same as those exposed by WebRequest. The only meaningful distinction between the two is the context-specific configurations that HttpWebRequest provides as class properties. This further highlights the elegance of the design of WebRequest. By taking a straightforward, generic approach to the problem, it can serve all possible specific use cases using the same patterns.