HTTP Web Requests in .NET
For whatever reason, when Microsoft developed the HttpWebRequest.GetResponse() method, if the status code of the response is 4xx or 5xx (for example a 404 not found response), it actually throws a WebException and you have to retrieve the Response object from the exception to test the status code of the response:
1: try {
2: HttpWebResponse response = (HttpWebResponse)request.GetResponse();
3: ...
4: } catch (WebException e) {
5:
6: HttpWebResponse response = (HttpWebResponse)e.Response;
7: HttpStatusCode status = response.StatusCode;
8: ...
9: }
In creating a custom client, I have found occasion where I would rather threat a 404 not found response, or a server error response like any other response. For example, it might be common in my application to get a 404 not found response returned by the web server, and I may be simply passing the response to the user. In this case, I would always have to catch the exception.
Ideally, I would like to derive a class from the HttpWebRequest and override the GetResponse() method to automatically handle WebExceptions associated with 4xx and 5xx responses. It appears that this is not possible. HttpWebRequest derives from the WebRequest class and provides additional properties and methods that enable interaction with servers using the Hypertext Transfer Protocol (HTTP). Instances of the HttpWebRequest class are automatically created by the WebRequest class. For example, an instance is created when the WebRequest.Create(uri) method is called and a Uniform Resource Identifier (URI) beginning with http:// is specified. Yet again, static methods are evil.
Plan B is to create a lightweight wrapper like so:
1: using System;
2: using System.Net;
3: using System.Runtime.Serialization;
4:
5: namespace WebRequestTest {
6: // Class that wraps a HttpWebRequest object
7: public sealed class MyHttpWebRequest {
8:
9: // The underlying HttpWebRequest object
10: private HttpWebRequest _request;
11:
12: // The constructor takes a HttpWebRequest object
13: public MyHttpWebRequest(HttpWebRequest request) {
14: this._request = request;
15: }
16:
17: // This method returns a HttpWebResponse object
18: public HttpWebResponse GetResponse() {
19: try {
20:
21: // If the response can be retrieved from the
22: // underlying request, return it
23: return (HttpWebResponse)this._request.GetResponse();
24: } catch (WebException e) {
25:
26: // Get the response from the WebException object
27: HttpWebResponse response =
28: (HttpWebResponse)e.Response;
29:
30: // If the exception is because of the status being
31: // 4xx or 5xx, return the exceptions response object
32: if ((int)response.StatusCode >= 400) return response;
33:
34: // otherwise rethrow the exception
35: else throw;
36: }
37: }
38: }
39: }
And now we can use the wrapper’s GetResponse() method to get an HttpWebResponse object regardless of the status code:
1: using System;
2: using System.Collections.Generic;
3: using System.Text;
4: using System.Net;
5:
6: namespace WebRequestTest {
7: class Program {
8: static void Main(string[] args) {
9:
10: // Request a valid web resource
11: HttpWebRequest request =
12: (HttpWebRequest)HttpWebRequest.Create("http://www.yahoo.com");
13:
14: // Create instance of wrapper for the
15: // purpose of getting the response
16: MyHttpWebRequest myrequest =
17: new MyHttpWebRequest(request);
18:
19: // Get the response object and display the
20: // status description
21: HttpWebResponse response = myrequest.GetResponse();
22: // This will display "OK"
23: Console.WriteLine(response.StatusDescription);
24:
25: // Request a non-existent web resource
26: request =
27: (HttpWebRequest)HttpWebRequest.Create("http://www.yahoo.com/thgy.html");
28:
29: // Create instance of wrapper for the
30: // purpose of getting the response
31: myrequest = new MyHttpWebRequest(request);
32:
33: // Get the response object and display the
34: // status description
35: response = myrequest.GetResponse();
36: // This will display "not found"
37: Console.WriteLine(response.StatusDescription);
38:
39: Console.ReadLine();
40: }
41: }
42: }