The code was all working just fine in test (heh, heh), but in production, suddenly we were getting
File or assembly name ox0vcwlz.dll, or one of its dependencies, was not found. File name: "ox0vcwlz.dll"
at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Boolean isStringized, Evidence assemblySecurity, Boolean throwOnFileNotFound, Assembly locationHint, StackCrawlMark& stackMark)
Very sad. Even more interesting was that on each run, the assembly name was different. OK, probably the XmlSerializer then. But why did it work in test, and not under other conditions.
It all became clear when we logged the full exception... Fusion says:
=== Pre-bind state information ===
LOG: Where-ref bind. Location = C:\WINNT\TEMP\ox0vcwlz.dll
LOG: Appbase = D:\Program Files\XXX
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/WINNT/TEMP/ox0vcwlz.dll.
Ah ha! Turns out the user context we were running under didn't have permissions to the c:\winnt\temp directory. Ouch. An easy fix, but not one that was intuitively obvious, at least to me. I knew that the XmlSerializer created dynamic assemblies, but I didn't know they had to be persisted to disk.
Something to think about.