URL Case Sensitivity and Assembly Loading

URL is case sensitive.

In Windows file names are case insensitive.

When these two meet, you can sense some inconsistence here.

When an http assembly is requested, it has to be copied into download cache, before it is returned to you.

Download cache is indexed by the URL. Now we have to consider the URL case sensitivity issue.

If we treat the URL as case sensitive, it means assembly http://foo/bar.dll will be considered as different from assembly http://foo/BAR.dll. If those two URLs mean different assemblies then we are fine. Unfortunately, if the web server is IIS, those two URLs really mean the same assembly. Weird problems happen when we consider them as different ( typical one is InvalidTypeCast error).

Thus we index the download cache by the URL as case insensitive.

This essentially means, URL for assembly is case sensitive, in the client side.

In .Net framework v1.0/v1.1, when we go probe for assembly foo, we will look for file foo.DLL, with the extension capitalized. If your web server treat URLs are case sensitive (like Apache), you need to be aware of this.

In .Net framework v2.0 beta 1 we changed the probing extension to small letter foo.dll. We realized this is a breaking change, and we change it back to capital letter foo.DLL in beta2.

Comments (8)

  1. Chango V. says:

    When using Assembly.LoadFrom(), the filepath/URL always seems to appear lowercase in the debugger output. Is this just ‘display’ normalization or some other rule regarding sensitivity applied?

  2. The filepath is the path in your local machine. Case sensitivity is irrelevant there, since Windows file system is case insensitive. I don’t think we (fusion) did anything there. Maybe someone else did the display normalization.

    I don’t know about the URL though.

  3. Craig Humphrey says:

    Perhaps it’s time for IIS to get case sensative… like the rest of the world… (perhaps a configurable option to turn case sensativity off/on?)

  4. They can’t. URL represent a resource in the server. When you say http://foo/BAR.dll, there is a file called BAR.dll in the server. If the file system is case insensitive, there is not much the web server can do.

  5. zbowling says:

    This is much more diffucult with us on the Mono team. Since we run on BSD, Linux and Solaris we have to deal with case sensitive file systems. On Mac and Windows, the file systems are case aware but in the subsystem they are case insensitive. This makes code portablity more of an issue. We offer the ability of hosting via apache your asp.net code. On Apache for win32, apache win32 is case insensitive. Apache on Linux/BSD/etc is case sensitive. The HTTP standard says that URLs should remain case insensitive. NTFS/HPFS is case insensitive and it even supports hard hard links (and symbolic links but that really is an OS thing) but the WIN32 subsystem prevents those features from comming to the surface for backword compatablity with fat. In a file name that exists which conflicts in case on the file system will cause Windows to freak out. I’ve tried it by modifiying my ntfs driver in Linux to think that ntfs is hpfs (but with the ntfs changes and enhancements) and write a file to the disk like that. It will blow up each time. Part of the issue with Linux’s read-write support for this is that if it rewrites the file it might get mixed up on the mapping with low level apps. We are dealing with the issue right now by mounting a folder in Linux with samba and using the samba mount on localhost (basicly a loop back windows share mount) and since samba has fixes for case insensitive it works when we port things to Linux for asp.net projects. Its not a fun issue.

  6. The whole unix/mac/windows combination is a nightmare. I don’t think you can find a perfect solution to all. Find a reasonable behavior.

    I think our behavior is quite reasonable, send the URL case sensitive to the web server, and treat the result as case-insensitive in the client side.

    I don’t really understand why file system needs to be case-sensitive. If you have foo and FOO in the same directory, there are something wrong.