« Enumerable.Sum never returns null | Main | Patching a Crash in Kensington MouseWorks »

June 5, 2009

Using If-Modified-Since in HTTP Requests

Conditionally requesting the download of a web page only if it has been modified after a given time seems like it should be as simple as setting the IfModifiedSince property and making the request:

HttpWebRequest request = (HttpWebRequest) WebRequest.Create(@"http://code.logos.com/blog/");

request.IfModifiedSince = new DateTime(2009, 6, 3);

using (HttpWebResponse response = (HttpWebResponse) request.GetResponse())

{

    if (response.StatusCode == HttpStatusCode.NotModified)

    {

        // page wasn't modified; use cached version

    }

}

But of course it’s not that simple (as some others have noticed).

The designers of HttpWebRequest decided that some particular HTTP status codes would cause a WebException to be thrown. (As far as I can tell, this list is undocumented, but 304 “Not Modified” is one of them.) This is a vexing exception, because the situation is hardly exceptional. In fact, because it can only happen if IfModifiedSince is explicitly set (or if request.Headers were modified), one could argue that it’s quite expected and intentional. To avoid duplicating logic in the try block (for handling 200 “OK”) and in the catch block (for handling “304” Not Modified), I wrote a utility method that swallows any WebException thrown due to a ProtocolError (e.g., an “invalid” HTTP status code):

public static class HttpWebRequestUtility

{

    /// <summary>

    /// Gets the <see cref="HttpWebResponse"/> from an Internet resource.

    /// </summary>

    /// <param name="request">The request.</param>

    /// <returns>A <see cref="HttpWebResponse"/> that contains the response from the Internet resource.</returns>

    /// <remarks>This method does not throw a <see cref="WebException"/> for "error" HTTP status codes; the caller should

    /// check the <see cref="HttpWebResponse.StatusCode"/> property to determine how to handle the response.</remarks>

    public static HttpWebResponse GetHttpResponse(this HttpWebRequest request)

    {

        try

        {

            return (HttpWebResponse) request.GetResponse();

        }

        catch (WebException ex)

        {

            // only handle protocol errors that have valid responses

            if (ex.Response == null || ex.Status != WebExceptionStatus.ProtocolError)

                throw;

 

            return (HttpWebResponse) ex.Response;

        }

    }

}

The code to consume this reads very similarly to the first snippet in this post; you just have to remember that normal errors (e.g., 404 “Not Found”) are reported through a valid HttpWebResponse, so its StatusCode property must be checked before acting on the response.

Posted by Bradley Grainger at June 5, 2009 11:36 AM

Trackback Pings

TrackBack URL for this entry:
http://blog.logos.com/mt-cgi/mt-tb.cgi/294

Comments

I am going to go beyond blog protocol and ask an unrelated question: I have been working with the Logos software and I am a C++ developer. So I decided to download your Libronix DLS Object Model Reference book (last updated 2004). I want to write software that interfaces with libronix books and original languages. Is there a newer manual than the one from 2004?
Steve Rives
Louisburg, Kansas
www . mrrives . com

Posted by: Steve Rives at June 17, 2009 6:41 PM

Hi Steve,

The LDLSOMR.lbxlls file on our FTP site is the latest copy. The underlying "object model" behind the Libronix DLS has not changed significantly since the publication of that resource: the basics of resources, searching, etc. are the same. Most of the major changes in LDLS 3.0 were in the UI layer, which hasn't ever exposed a public interface for automation (except for a few dialogs and reports that officially documented the parameters with which they could be invoked).

Note that the object model was designed more for "VB style" COM clients (i.e., IDispatch clients), rather than C++. It's certainly not impossible to use from C++, but it may not be the best "fit".

Bradley

Posted by: Bradley Grainger Author Profile Page at June 17, 2009 9:33 PM

You may also wish to check out this forum thread, particularly Bob's posts: http://community.logos.com/forums/p/92/665.aspx

Posted by: Bradley Grainger Author Profile Page at June 19, 2009 10:47 AM

Post a comment




(you may use HTML tags for style)