Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't I set If-Modified-Since on a WebClient?

I am using WebClient to retrieve a website. I decided to set If-Modified-Since because if the website hasn't changed, I don't want to get it again:

var c = new WebClient();
c.Headers[HttpRequestHeader.IfModifiedSince] = Last_refreshed.ToUniversalTime().ToString("r");

Where Last_refreshed is a variable in which I store the time I've last seen the website.

But when I run this, I get a WebException with the text:

The 'If-Modified-Since' header must be modified using the appropriate property or method.
Parameter name: name

Turns out the API docs mention this:

In addition, some other headers are also restricted when using a WebClient object. These restricted headers include, but are not limited to the following:

  • Accept
  • Connection
  • Content-Length
  • Expect (when the value is set to "100-continue")
  • If-Modified-Since
  • Range
  • Transfer-Encoding

The HttpWebRequest class has properties for setting some of the above headers. If it is important for an application to set these headers, then the HttpWebRequest class should be used instead of the WebRequest class.

So does this mean there's no way to set them from WebClient? Why not? What's wrong with specifying If-Modified-Since in a normal HTTP GET?

I know I can just use HttpWebRequest, but I don't want to because it's too much work (have to do a bunch of casting, can't just get the content as a string).

Also, I know Cannot set some HTTP headers when using System.Net.WebRequest is related, but it doesn't actually answer my question.

like image 678
Superbest Avatar asked Nov 09 '22 16:11

Superbest


1 Answers

As unwieldy as it may be, I have opted to subclass WebClient in order to add the functionality in a way that mimics the way WebClient typically works (in which headers are consumed by / reset after each use):

public class ApiWebClient : WebClient {
  public DateTime? IfModifiedSince { get; set; }

  protected override WebRequest GetWebRequest(Uri address) {
    var webRequest = base.GetWebRequest(address);
    var httpWebRequest = webRequest as HttpWebRequest;
    if (httpWebRequest != null) {
      if (IfModifiedSince != null) {
        httpWebRequest.IfModifiedSince = IfModifiedSince.Value;
        IfModifiedSince = null;
      }
      // Handle other headers or properties here
    }
    return webRequest;
  }
}

This has the advantage of not having to write boilerplate for the standard operations that WebClient provides, while still offering some of the flexibility of using WebRequest.

like image 74
Thomas S. Trias Avatar answered Nov 15 '22 07:11

Thomas S. Trias