In this post I will share a solution that I reached the other day regarding an InvalidOperationException that I was receiving when attempting to consume a SOAP web service with DIME attachments. Hopefully this will save you some time, as I was unable to find a good solution online when I encountered the error. DIME attachments are a Microsoft standard that has recently been deemed obsolete. Basically, it's a method of transmitting binary data via SOAP, in which the raw data is delivered after the SOAP envelope. By keeping the data outside of the envelope, it does not have to be Base64 encoded (which would be required to keep the XML valid). Subsequently, the attachment does not have to be consumed by an XML parser on the client-side. This approach dramatically increases the performance of both the client and the server. Although effective, DIME has already been replaced by a newer standard called MTOM. However, DIME is still used today by several established APIs and will probably continue to be used unless an upgrade is absolutely warranted. To work with DIME attachments, Microsoft Web Service Enhancements 2.0 will need to be used.
In my efforts to invoke the web service method and download an attachment, I constantly received the following exception...
InvalidOperationException: Client found response content type of 'application/dime', but expected 'text/xml'
This was somewhat puzzling to me because I did not know what was forcing my client to expect "text/xml". I was hoping there was a ContentType setting I could simply modify that would fix the error, but I was unable to find one. At this point, I was certain that the root of the issue was under the covers. In other words, it wasn't my code causing the problem, it had to be one of the underlying dependencies. So, I went ahead and did some digging into the MSDN documentation and found an article on the topic. One paragraph in particular grasped my attention, specifically the last sentence...
In order to use the WSE DIME support with a Microsoft .NET client application in Visual Studio, you must add a reference for the Microsoft.Web.Services2.dll assembly. Also, after adding a Web reference to the DIME-based Web service, you must modify the proxy class in the References.vb file so that it inherits from the Microsoft.Web.Services2.WebServicesClientProtocol class in WSE.
Sweet! At this point, I thought I had this all figured out. Apparently, the exception I was receiving was caused by the proxy class that is automatically generated by ASP.NET. By default, this class inherits System.Web.Services.Protocols.SoapHttpClientProtocol. According to MSDN, this inheritance will not work with DIME attachments, so it needs to be changed to a class that comes with the WSE toolkit. By using Lutz Roeder's Reflector, which is a wonderful tool, I verified that the only acceptable content types in the default proxy class are text/xml and application/soap+xml...

So that was definitely the problem. This glimmer of hope was shattered when I was completely unable to find the generated proxy class in my solution. Where on Earth is this References.vb file located?! It did not exist in my project because it was a "Web Site" project, and therefore the proxy class was being generated based on the WSDL and compiled on-the-fly by the web server. How do you modify code that is generated on-demand, behind the scenes, by ASP.NET? You don't. Damn!
This frustrated me quite a bit, especially since MSDN did not mention anything about my situation, which is one that I would consider to be common. What I ended up having to do was create a new class library with the sole purpose of invoking the web service. Then I replaced my web reference in the web site project with a reference to this new class libary. This theoretically simple process turned out to be a little confusing, so allow me to step you through it (note that I am using Visual Studio 2005). To begin, I added a new Class Library project to the current web site...

As already mentioned, this class library will solely perform the task of invoking the web service. So, the web reference needs to be removed from the web site project and then re-added to this new class library. When you do this, Visual Studio will generate a proxy class for the service that you will be able to modify accordingly to prevent the InvalidOperationException from being thrown. Here is a screenshot illustrating where the proxy class is located in Solution Explorer...

Open up the Reference.vb file (if you code in C# it will be called Reference.cs) so that you can modify the Inherits statement per MSDN's recommendation...
Namespace WebReferenceName Partial Public Class ServiceName Inherits Microsoft.Web.Services2.WebServicesClientProtocolInherits System.Web.Services.Protocols.SoapHttpClientProtocol
And that should be the only thing that needs changed. Prior to building, you may want to go into the class library configuration and set it to release mode so that debugging symbols are not generated. Once the library builds successfully, you will need to add a reference to it in your web site project. When you need to call the method that returns DIME attachments in your web site project, simply instantiate the web service within the class library like this...
Dim Service as New MyClassLibrary.WebReferenceName.ServiceName()
This will prevent the InvalidOperationException from being thrown. Every time you update the web reference in the class library, you will have to go back in and change the inheritance of the proxy class again, which is pretty lame. Unfortunately, this is the best solution I was able to come up with. I hope somebody finds this helpful. If you have any questions or relevant insight, please leave a comment.
Since you were one of my favorite users on asp.net forum who had very good ideas about the forum itself, I would like to know why is your account deactivated there?
But, look at it on the bright side - now you have enough time to write articles on your blog ;)
If you honestly think that my intentions were not good, I am sorry. Everything I said on the forums was meant to be helpful. I'll admit, sometimes I was somewhat rude when I replied to people. But, I intended on conveying my message in a way that would grab people's attention. And I still think people are benefitting from such replies to this day.
Thanks for commenting.
Guess What?
There are a few basic guidelines you should be aware of before leaving a comment…
- If you choose to display your email address, it will not be detected by spam bots
- Comments are limited to 3,000 characters; so far you have used none of them
- HTML will be encoded; links and line breaks will be converted automatically
- Comments containing five or more links will be subject to moderation
