I took an interesting trip to Web Services Hell today and thought I’d share the solution.
I was authoring a .NET 2.0 client that had to make calls into a web service authored in Java and hosted on a Tomcat server. Authentication worked fine but as soon as I tried to do actual work I got the following rather cryptic error:
System.InvalidOperationException: Unable to generate a temporary class (result=1). error CS0029: Cannot implicitly convert type 'foo.bar.RequiredCodeType' to 'foo.bar.RequiredCodeType[]'
Uh-oh. Something in the bowels of Visual Studio has thrown a rod and I’m supposed to figure out what it is. It sure does feel like Monday morning.
Google presented me with a couple of likely rabbit trails:
1) Most “Unable to generate a temporary class” errors are caused by permission issues where the runtime wants to generate on-the-fly code into some temp directory it doesn’t have permissions for. I knew this wasn’t likely the problem because the additional error message info isn’t complaining about “file not found” or “can’t write to file” types of errors.
2) There are various differences between Java-authored and CLR-based web services that can cause problems, but none of those seemed to apply here, and a nearly identical service coming from the same system was chatting merrily away with the same .NET client without difficulties.
Finally I stumbled on a BizTalk Server issue that sounded pretty close. In this case, BizTalk gets compiler errors talking to a web service where an attempt is being made in some generated proxy class code to assign some type to an array of those types, or vice versa. This happens whenever the WSDL for the web service uses “unbounded” as the value for a MaxOccurs assignment.
That’s essentially what’s happening in my error above; RequiredCodeType is being assigned to an array called RequiredCodeType[]. I wasn’t working with BizTalk but I’m willing to bet that it’s using the same code generator as does Visual Studio, or they at least share a common lineage. And, RequiredCodeType is associated with MaxOccurs=”unbounded” in the WSDL for the web service.
The published workaround in the above BizTalk article is to hand-correct the generated code, which erroneously adds a set of angle brackets to a name when it doesn’t need to.
So I poked around and found the generated Reference.cs file for the web service (not visible, as far as I know, from Visual Studio; I had to go look in the file system for it). Sure enough, I found a couple of declarations of the form:
private RequiredCodeType[ ] [ ] scoreFactorsField;
This is just what the BizTalk article said to expect; a multidimensional array being declared for an unbounded collection. I took off the second set of angle brackets. recompiled, and all was well.
WARNING: You’ll have to put the fix back in every time you refresh the web service in Visual Studio, or take any other action that will cause this code to be regenerated.
The question I didn’t resolve is whether this is truly a bug in Microsoft’s code generator or something peculiar in the WSDL provided by the web service host. My political reality is that I’m the token .NET guy in a Java shop and they aren’t going to be receptive to tweaking their WSDL for me, so I didn’t pursue it. Besides, my gut says it’s probably an issue on the Microsoft side.
{ 1 comment… read it below or add one }
Excellent post – I love this kind of investigative research that pulls in something from an apparently unrelated angle that turns up a valuable clue.
I think you’re on the right track – I worked on a project a couple of years ago with similar circumstances. In our case, the breakdown was because the Java team were *hand coding* their SOAP packets, and introduced bogus characters that caused the service proxies to barf on the .NET side.
We used SOAPScope a lot to ferret the issue out and pinpoint it. The Java guys were in denial until we showed them that it was their fault… ;-)