Thursday, September 21, 2006

.NET Assembly Resolution

Thanks to .NET, DLL Hell is officially ended. But I at least still find myself in DLL Heck from time to time (thanks to Scott Adams for the term).

We still seem to have too many issues where something works on one machine but not on another (usually it works on the developer's machine but not when we install it on a director's laptop to show him that we haven't spent the last month just browsing the Internet).

Our app has a simple footprint: we bung everything, including third-party controls, into a bin folder. How can anything go wrong? The loader looks in the app folder for stuff first, doesn't it? WRONG!

We get away this simple-minded view most of the time because (and I know you'll tell me off for this) we aren't yet strongly naming our assemblies. In this case, the loader only looks in the app folder (and below).

But for strongly named assemblies, the loader looks in the GAC first. This makes sense. The loader is always looking for a specific version of an assembly; you control which assembly versions are loaded for your app via the version policy, not by shadowing shared DLLs with your own copies in the app bin folder.

Here are some links that explain all this unambiguously.

Assembly Versioning (from the MSDN Library)

Resolving Names to Locations (from .NET Common Language Runtime Components by Don Box & Chris Sells)

Useful diagram from the second link:

Bonus information from that book extract: if you put <developmentMode developerInstallation="true" /> in the configuration/runtime node of the machine.config file, the loader first looks in the path specified by the DEVPATH environment variable.

Friday, September 08, 2006

HTTP Partial Get - The Point

Got so into blogging the "how" in the last post that I forgot about the "why", although I hope that's fairly obvious.

The W3C puts it like this:

The partial GET method is intended to reduce unnecessary network usage

and this:

A server MAY ignore the Range header. However, HTTP/1.1 origin servers and intermediate caches ought to support byte ranges when possible, since Range supports efficient recovery from partially failed transfers, and supports efficient partial retrieval of large entities.

I.e.

  1. Keep the Internet clean (hear that, spammers?)
  2. Speed up client requests.

I'm sure I had a point, but it's gone. The thought of all the crap floating around in the ether has depressed me too much to think. I think I need to see Marvin to cheer me up.

BTW our web hosting company honours ranges so perhaps it's not all that bad.

HTTP Partial Get

Part of our application allows the user to drag/drop document links onto a window. When the link is a web page shortcut, I wanted to get the page title as the description for that link. The only way I could find to do this was to download the page using an HttpWebRequest object, and parse for the <title> tag.

This is OK except that I didn't want to download an entire page just to get a piece of information that, if present, will be somewhere near the top. Enter the partial get capability of HTTP 1.1. If you add a "range" header to the GET request, the server should return only the specified byte range from the document. Here is the code I used.

 

   PrivateFunction GetWebPageTitle(ByVal url As String) As String

 

       Dim request As HttpWebRequest

       Dim response As WebResponse

       Const bytesToGet As Integer = 1000

 

        request = DirectCast(WebRequest.Create(url), HttpWebRequest)

        request.AddRange(0, bytesToGet - 1)

        response = request.GetResponse

 

        ...

 

   EndFunction

 

However, the operative word here is should (i.e. it's not mandatory behaviour). In half-a-dozen web sites I tried (including microsoft.com), only one took any notice of my range request:

Some things to note:

  • The response code is 206 (Partial Content)
  • Content-Length = 1000
  • Content-Range = 0-999 (the first 1000 bytes) of a total of 126,444
  • Accept-Ranges: Bytes tells us the server recognizes the Range header in the GET request (which we now know, but we could have issued a HEAD request to find this out)
  • The well-behaved web site is w3.org (of course!)

(The screenshot is from Wireshark, formerly Ethereal.)