Reputation: 4281
I 've been banging my head with this to to avail. Any ideas are much welcome!
I have a client/listener application in vb.net using MSMQ and it works 100% fine when I do not use sgen.exe to generate the serializations on compile time.
When using sgen, it fails on the listener part.
qOrders.Formatter = New XmlMessageFormatter(New Type() {GetType(InfoMessage)})
m = qOrders.EndReceive(e.AsyncResult)
It bombs on m. m.Body has the error "Cannot deserialize the message passed as an argument. Cannot recognize the serialization format."
and the rest of the properties also have errors of not receiving a value.
The assembly is strong named and the App.XmlSerializers.dll is also signed correctly. I know the dll is used because I can't delete it while the program is running.
The InfoMessage class is a simple public class with 3 public string members. Inspecting the dll with Reflector, I do see that sgen has generated an InfoMessageSerializer class.
The problem is not on the client side because I delete the dll and run the listener, it works as usual.
So, what could be wrong here? :o
Thanks,
John
Edit: Link to Listener source: http://pastebin.com/TqWfLVJ0
Upvotes: 2
Views: 582
Reputation: 13529
There is a design limitation of sgen
output. This limitation was never removed:
These generated assemblies cannot be used on the server side of a Web service. This tool is only for Web service clients and manual serialization scenarios.
Basically, you are not expected to run sgen
to make the server side of a web service faster, because XmlSerializer
startup time is not a crucial factor of its performance (in contrast with some types of clients).
Of course, sgen
can be used on the server side in a non-web service scenario, as long as you do not pass any XmlAttributeOverrides
to the constructor of XmlSerializer
.
With MSMQ, there is a choice of binary and XML serialization, and your code chooses the latter here:
qOrders.Formatter = New XmlMessageFormatter(New Type() {GetType(InfoMessage)})
So let's have a look at how MessageQueue
creates an XmlSerializer
. The following is a method of XmlMessageFormatter
taken from System.Messaging.dll
, .NET 4.0. Its .NET 2.0 counterpart is similar.
private void CreateTargetSerializerTable()
{
if (!this.typeNamesAdded)
{
for (int index = 0; index < this.targetTypeNames.Length; ++index)
{
Type type = Type.GetType(this.targetTypeNames[index], true);
if (type != (Type) null)
this.targetSerializerTable[(object) type]
= (object)new XmlSerializer(type);
}
this.typeNamesAdded = true;
}
if (!this.typesAdded)
{
for (int index = 0; index < this.targetTypes.Length; ++index)
this.targetSerializerTable[(object) this.targetTypes[index]]
= (object)new XmlSerializer(this.targetTypes[index]);
this.typesAdded = true;
}
if (this.targetSerializerTable.Count == 0)
throw new InvalidOperationException(Res.GetString("TypeListMissing"));
}
As you can see, MSMQ does not supply XmlAttributeOverrides
, unlike web services server side code in the framework. Still, there are other people who have trouble with combining XmlMessageFormatter and sgen
.
My guess is that sgen
can still be made to work with MSMQ because MSMQ does not use XmlAttributeOverrides
, but you will have to make sure that you are not using the proxytypes
command line option, and that you are still moving way outside of what Microsoft ever tested.
I would advise looking at these possibilities:
sgen
with MSMQ./proxytypes
option with sgen
.SGenUseProxyTypes
in case you invoke sgen
from your project file (look here to see how).Upvotes: 2