I’ve discovered something that might be a bug in some way.
In one of our web applications, one of the developers wrote a user control (ASCX). The ASCX file contained a DIV with the “runat=server” attribute named (just of the sake of the sample) “X”. The ASCX.cs file contained another property called “x” (mind the case change!).
Since the compiler is case sensitive, there was no problem with this and the whole thing compiled and run, specifically it run from Visual Studio while debugging, the problem started when we precompiled the application.
In our build process, we precompile the web applications using the ASP.NET Compiler (through MSBuild, of course 😉 ) and since there was no compilation problem, everything went fine and the build succeeded.
We put the new build in a dev machine and started working with it. When we reached a page that used that control we got the “Ambiguous match found” exception. After searching for it in the newsgroups I found that it is a reflection related problem, so I fired up my faithful WinDbg and dived in.
I attached to the ASP.NET worker process and it broke in when the exception was thrown. I looked at the call stack (using !clrstack) and saw a call to “System.RuntimeType.GetField”, a reflection function used to get a field of an object.
OS Thread Id: 0xf38 (14)
019eecb0 77e55dea [HelperMethodFrame: 019eecb0]
019eed54 79617ef1 System.RuntimeType.GetField(System.String, System.Reflection.BindingFlags
I run “dds 019eed54” (this address is the address of the stack frame) to see what’s on the stack and get the addresses/values of the two parameters in the function.
The first two lines (shown above) contains the addresses/values (depending on the type and number of parameters passed to the function, in our case we have only two) of the function. The second column contains the addresses/values. In our case, since the first parameter is a string, the value 0263588c is actually the address of a string, so I used !dumpobject to see its value and saw that it was “x”.
The second parameter is an enumeration, so the value represents the integer value of that enum flag. I looked in Reflector and saw that the value 1 belongs to BindingFlags.IgnoreCase.
At that point I still didn’t figure out the problem, so I went back to reflector and took a look at the precompiled assembly that this code was compiled into and then saw that I had two protected fields, one named “X” and one named “x”.
Bingo! that’s the problem, staring me back from the screen.
To sum things up, while this code is correct compiler-wise (two parameters with the same characters but different casing are two different parameters), the implementation that tries to access some of it uses a case insensitive reflection search, which causes the bug.
Until I get more information from Microsoft, I suggest making sure in any ASP.NET application that is precompiled to avoid having the same names with different casing to variables in the ASPX/ASCX page and its code behind.