natli
natli

Reputation: 3822

How to override a .NET class

As an example I am trying to alter the GetResponse() function of HttpWebRequest

class HttpWebRequest_Override : HttpWebRequest
{
    public HttpWebRequest_Override(System.Runtime.Serialization.SerializationInfo SerializationInfo, System.Runtime.Serialization.StreamingContext StreamingContext) 
        : base(SerializationInfo, StreamingContext) { }

    public override WebResponse GetResponse()
    {
        //Edit GetResponse() code here.
    }
}

However I can't find the standard code for GetResponse() anywhere. Am I expected to write one from scratch? I'd like to Copy+Paste the original code in and then alter it. I already tried looking here but that didn't help much.

To test if I was even on the right track, I commented out GetResponse() and tried to use the HttpWebRequest_Override as-is (with only the constructor in).

And then using it like:

public static string DownloadText(string url)
{
    try
    {
        var request = (HttpWebRequest_Override)WebRequest.Create(url);
        request.Proxy = null;
        var response = (HttpWebResponse)request.GetResponse();

        using (var reader = new StreamReader(response.GetResponseStream()))
        {
            return reader.ReadToEnd();
        }
    }
    catch (Exception ex) { return "error_program : "+ex.Message; }
}

But this throws the error:

Unable to cast object of type 'System.Net.HttpWebRequest' to type 'bulktest.HttpWebRequest_Override'.

So two questions:

Why isn't the class working, and where can I find the code for .NET classes so I can alter them?

Upvotes: 2

Views: 5614

Answers (3)

tvanfosson
tvanfosson

Reputation: 532445

WebRequest.Create doesn't create an instance of your class, it creates an instance of HttpWebRequest, which you derive from. While you can cast an instance of a child as it's parent, you can't cast an instance of the parent as the child. The parent isn't guaranteed to have all of the methods of the child, whereas the child is guaranteed to have to the methods of the parent.

You can register custom protocols that are handled by your own, derived class or, via configuration, register your class to handle the default protocols. Whether you need to do this is an open question. From your example, a simple wrapper might be sufficient. The wrapper would take a HttpWebRequest instance in the constructor and delegate the standard WebRequest methods to that instance. Any new methods would use the underlying instance's methods for their work and layer your additional functionality on top of it.

EX:

 var request = new WebRequestWrapper((HttpWebRequest)WebRequest.Create(url));
 var html = request.DownloadText();

Where your class might look like:

 public class WebRequestWrapper
 {
      private HttpWebRequest _request;

      public WebRequestWrapper(HttpWebRequest request)
      {
          this._request = request;
      }

      public string DownloadText()
      {
          using (var response = (HttpWebResponse)this._request.GetResponse())
          using (var reader = new StreamReader(response.GetResponseStream()))
          {
              return reader.ReadToEnd();
          }
      }
 }

FWIW, I don't like catching the exception and returning a string. I'd rather let the exception bubble up since the method returns a string.

Upvotes: 1

Dmytro Shevchenko
Dmytro Shevchenko

Reputation: 34581

You can browse .NET Framework source in different ways, for example, via .NET Reflector. But you can also see it online - for example, here's the source of HttpWebRequest.GetResponse():

http://typedescriptor.net/browse/members/326374-System.Net.HttpWebRequest.GetResponse()

As noted by others, you don't have to copy-paste the original code. But it's still good to know how it works.

Upvotes: 0

leppie
leppie

Reputation: 117220

Custom web request types can be 'injected' via the .config file.

Have a look here: http://msdn.microsoft.com/en-us/library/bc0fhzk5.aspx

Upvotes: 1

Related Questions