Playing with MSMQ transport in WSE2
As i I've been working in the new messaging framework we are developing i started to look for existing implementations for custom transports for WSE2.
So far i have found the following: MSMQ, SMTP, UDP and SQL. The one using MSMQ is from the excellent writer and MVP Roman Kiss (published at CodeProject) and i enjoyed this article very much. Roman also have written other fine articles, so give then a look.
Well, let's get to the point. I've been using this code
as a base to build some MSMQ transport for WSE2 and I
stumbled with a very annoying bug.
In the code that
registers a new SoapReceiver the article sample code
always pass a new instance of a receiver object instead of
passing the Type of the receiver you want to use.
The
SoapReceivers.Add method allows
registering a new receiver using two different overloads:
using an object instance or an object type.
The two
behaviors go in the opposite direction as one uses always
the same receiver instance for all process and the other
way implies a creation of a new receiver at runtime when
it’s needed.
So, I realize that the code in the
SoapMsmqInputChannel from the article
only supports only the first way of doing things, that’s
it passing an instance and not an object type.
This
bug was annoying because the behavior of the failure was
very strange. When I try to pass an object type to the
SoapReceivers.Add method all went fine
until I discover that the message wasn’t dispatched to my
receiver object because it's never found in the receivers
collection.
Fortunately the bug is very easy to fix.
Just add the code to take into account that the thing you
found in the SoapReceivers collection maybe it’s an
instance of an SoapReceiver object or maybe it’s an object
Type and it’s your responsibility to create the
instance.
To make the story short, the method Enqueue can be rewritten as follows:
public override void Enqueue(SoapEnvelope message)
{
//
get the receiver for this endpoint
SoapReceiver receiver;
object recv =
SoapReceivers.Receiver(_endpoint);
if( recv is Type )
{
receiver =
(SoapReceiver)Activator.CreateInstance((Type)recv);
}
else
{
// try to
cast
receiver = recv as SoapReceiver;
}
if(receiver != null)
{
// synchronous
process message workflow
// through
the pipeline to the endpoint handler
receiver.ProcessMessage(message);
}
else
throw new Exception(string.Format(
"Missing a receiver for endpoint={0}",
endpoint.Address.Value));
}
I hope that this post help someone with the same problem I come across. I will continue working with this code making some enhancements and adding some features we need, and I will be posting my experiences here.
Best regards,
PS: i haven't compiled the above code (i'm writing
it right here and now) so excuse me if it has some error
or imperfection.
Andrés G Vettori
MCSE/MCSD/MCT
Leader of the C# Community of the
Microsoft Users Group Argentina