Hi,
I could actually do with some design advice on what I am trying to achieve
with this MSMQ problem. We are writing a web app. where unfortunately we have
to deal with a product called Navision where by we have to communicate via
MSMQ. It's not the way I would have done it but there you go, this piece of
the architecture cannot change.
As this MSMQ process might be quite time consuming, I want to take advantage of
ASP.NET 2.0 asynchronous page’s functionality. The problem I have is I am
struggling with the whole asynchronous model. As stands I have the web
application that will call a component I have lovingly called the MSMQAdapter.
The MSMQAdapter takes a domain object and takes care of placing the message on
the queue and retrieving a response message from a different queue which are
married together by CorrelationId. If I was to do this synchronously, I have
no problem with how to do this. But asynchronously I am struggling. The web
app calls the following code in the MSMQAdapter:
public void CalculateOrder(ShoppingCart cart)
{
try
{
OrderBuilder orderBuilder = new
OrderBuilder(OrderBuilder.OrderMessage.CALCULATEORDER);
MSMQHelper helper = new MSMQHelper();
helper.Request(orderBuilder.Build(cart));
}
catch (Exception ex)
{
log.Error("MSMQHelper.Request", ex);
throw ex;
}
}
The request method looks like this:
public void Request(string xml)
{
_correlationId = SendMessage(xml);
_receiveQ = GetQueue(LawConfig.MSMQ.ReceiveMSMQ);
_receiveQ.MessageReadPropertyFilter.CorrelationId = true;
_receiveQ.PeekCompleted += new
PeekCompletedEventHandler(ReceiveQ_PeekCompleted);
_receiveQ.BeginPeek(_timeOut);
}
The ReceiveQ_PeekCompleted handler looks like this:
private void ReceiveQ_PeekCompleted(object sender, PeekCompletedEventArgs e)
{
MessageQueue messageQueue = sender as MessageQueue;
using (Message message = messageQueue.EndPeek(e.AsyncResult))
{
if (!message.CorrelationId.Equals(_correlationId))
{
messageQueue.BeginPeek(_timeOut);
return;
}
}
using (Message message =
messageQueue.ReceiveByCorrelationId(_correlationId))
{
//DO processing
}
}
This method will do some calculation with the message and then I would like to
return a domain object to the web application but I do not know how to do this?
How can I get the domain object back to the web application? Do I have to
raise some custom events in order to get back to the web application or is
there a better way? Is there a way I can call this method asynchronously from
the web application?
Sorry for the length of this email but I am really stuck.
Cheers
Paul
[EMAIL PROTECTED]
> Date: Sun, 6 Aug 2006 10:07:08 +0000> From: [EMAIL PROTECTED]> Subject: Re:
> [ADVANCED-DOTNET] ReceiveByCorrelationId + MSMQ> To:
> [email protected]> > Hi,> Thanks for the help. Is there a
> way to take the message off the queue without calling ReceiveByCorrelationId
> because behind the scenes that method iterates through every message in the
> queue and then takes the message off the queue and I doubt it is thread
> safe.> > Thanks> [EMAIL PROTECTED]> > > > > Date: Sat, 5 Aug 2006 17:03:45
> -0500> From: [EMAIL PROTECTED]> Subject: Re: [ADVANCED-DOTNET]
> ReceiveByCorrelationId + MSMQ> To: [email protected]> >
> Sample below...> > A few thoughts/comments - first, I think you always want
> to EndPeek. I> remember reading somewhere that the API docs state that the
> framework does> not promise to behave nicely if you forget to. Second,
> EndPeek will throw an> exception if BeginPeek times out. I added the 'using'
> statements on the> messages because they are disposable and I am a little
> superstitutious about> that more than that I have ever actually seen that
> cause a problem. It would> seem weird to me that a Message object would
> actually hold on to some> important unmanaged resource, but who knows?
> Reflector doesn't make it> obvious. Maybe someone can comment on that. FWIW,
> I highly recommend you set> up a little functional test in NUnit or whatever
> it is you use to write your> tests to simulate the situation you are looking
> for and prove it out to> yourself. You don't even have to have Navision
> running. There are few things> like the comfort of a good, green bar to aid
> in understanding.> > I hope that helps!> > Thanks,> Jef Newsom> > > private
> void ReceiveQ_PeekCompleted(object sender, PeekCompletedEventArgs e)> {>
> try> {> MessageQueue messageQueue = sender as MessageQueue;>
> using(Message message = messageQueue.EndPeek(e.AsyncResult))> {>
> if(!message.CorrelationId.Equals(_correlationId))> {>
> messageQueue.BeginPeek(_timeOut);> return;> }> }>
> using(message = messageQueue.ReceiveByCorrelationId(_correlationId))> {>
> // do something with it.> }> }> catch(MessageQueueException
> e)> {> if(e.MessageQueueErrorCode ==
> MessageQueueErrorCode.IOTimeout*)*> * {*> // log it, peek again,
> whatever you think is the right thing to do.> }> }> }> > > On 8/5/06,
> Paul Cowan <[EMAIL PROTECTED]> wrote:> >> > Hi,> >> > THe eventargs contains
> the message. I have the following event handler> > for PeekCompleted:> >> >
> private void ReceiveQ_PeekCompleted(object sender, PeekCompletedEventArgs> >
> e)> > {> > if (e.Message.CorrelationId != _correlationId)> > {> >
> messageQueue.BeginPeek(_timeOut);> > return;> > }> >
> MessageQueue messageQueue = sender as MessageQueue;> > Message message =
> messageQueue.EndPeek(e.AsyncResult);> > }> >> > My question is what if there
> is an error on the other side and the message> > never gets placed onto the
> queue?? How can I timeout gracefully if> > BeginPeek is being called each
> time?> >> > Thanks> > Paul> > [EMAIL PROTECTED]> >> >> >> > > Date: Sat, 5
> Aug 2006 14:16:28 -0500> From: [EMAIL PROTECTED]>> > Subject: Re:
> [ADVANCED-DOTNET] Recei
===================================
This list is hosted by DevelopMentor® http://www.develop.com
View archives and manage your subscription(s) at http://discuss.develop.com