Why are my queued WCF messages silently disappearing?
Asked Answered
R

5

9

I have a transactional MSMQ queue setup on server THOR. I am able to post messages to that queue from a workstation with the following code:

var queue = new MessageQueue("FormatName:Direct=OS:thor\\private\\myqueue");
using (var tx = new MessageQueueTransaction())
{
   tx.Begin();
   queue.Send("test", tx);
   tx.Commit();
}

However, when I attempt to connect using WCF my messages never appear in the queue. Here is the configuration I'm using:

<system.serviceModel>
  <bindings>
    <netMsmqBinding>
      <binding name="ClientNewsFeedServiceBinding" durable="true" exactlyOnce="true">
        <security mode="None" />
      </binding>
    </netMsmqBinding>
  </bindings>

  <client>
    <!-- NewsFeed Service -->
    <endpoint name="INewsFeedService"
              address="net.msmq://thor/private/myqueue"
              binding="netMsmqBinding"
              bindingConfiguration="ClientNewsFeedServiceBinding"
              contract="Service.Contract.INewsFeedService" />
  </client>
</system.serviceModel>

And the code:

using (var tx = new TransactionScope())
{
   var cf = new ChannelFactory<INewsFeedService>("INewsFeedService");
   var service = cf.CreateChannel();
   service.TestMessage("test");
   ((IChannel)service).Close();
   tx.Complete();
}

I get no exceptions of any kind, but there is no message posted on the queue on THOR. Any ideas? I don't even know how to debug this since it just silently fails.

UPDATE

If I change my MSMQ URI to 'net.msmq://localhost/private/myqueue' then it will post to a local transactional queue I have setup. The setup of the queue itself is identical (as in, I performed the same steps to create both the localhost and THOR queues).

React answered 5/10, 2010 at 15:55 Comment(3)
Do these messages show up in your transactional dead-letter queue??Actinomycin
No, nothing shows up in the transactional DLQReact
updated my answer - have you checked your DTC on all machines involved??Actinomycin
A
3

I believe if you make your queue transactional on the MSMQ server side, you need to specify a few more settings in your WCF binding config - try this:

<bindings>
    <netMsmqBinding>
      <binding name="ClientNewsFeedServiceBinding" 
               durable="true" exactlyOnce="true">
        <security mode="None" />
      </binding>
    </netMsmqBinding>
  </bindings>

If I'm not mistaken, you need to add the durable="true" and exactlyOnce="true" attributes to your netMsmq binding for this to work.

There's a really good tutorial on how to get MSMQ and WCF to work nicely together:

Tom covers transactional queues in part 3, and mentions:

The exactlyOnce="true" attribute is WCF-speak for using a transactional message queue.

The durable=true only means to have the messages flushed to disk right away, instead of keeping them in server memory. It's slower, but in case of a server crash or power interrupt, messages aren't lost. Classic speed vs. reliability tradeoff....

Update: since you're going "across" machine boundaries, and you're using transactional queue - have you checked the DTC (Distributed Transaction Coordinator) on all machines involved?? Check out Tom's blog part 3:

Check DTC Configuration

Our epic journey is almost at an end. In fact if you're still playing along at home, you can try running the application with the transactional queues to see if it's working. If it's failing, one possible cause is problems with your Distributed Transaction Coordinator configuration. Here are a few things to try:

Actinomycin answered 5/10, 2010 at 16:21 Comment(1)
Tried that, no go. I added an update to my original post to say that I AM able to run the WCF code if I update my MSMQ URI to point to localhost instead of THOR.React
C
1

I had the same problem. After trying out all the ideas listed here I started looking for something else. It turned out that when you select the security mode None the sender properties of me message are left empty (see picture below).

MSMQ Message properties

Such message will be accepted when it is sent to a localhost but it will be rejected by the remote server.

In order to make it working you have few options:

  1. Enable authentication
  2. Grant Send permissions to the ANONYMOUS LOGON

The first option if of course safer but it requires MSMQ to be installed with Active Directory integration.

Confederate answered 24/11, 2013 at 13:3 Comment(1)
Not sure about WCF, but this solved a similar problem I was having with NServiceBus and MSMQ sending messages to a different machine and having them dropped silently. Adding "ANONYMOUS LOGON" permissions to the queue fixed it (even though I already had "Everyone" with full control!)Seaddon
S
0

Try completing the transaaction scope before you close the channel.

When you close the channel you lose contact with it, it therefore has an uncommitted transaction, which is eventually discarded.

Shorthorn answered 5/10, 2010 at 16:0 Comment(1)
That didn't work. What you say makes sense, but didn't seem to make a difference.React
N
0

I had similar problem, so I hope this checklist helps:

  1. Connectivity: I suppose that thor DNS entry is working, isn't it? Check that it makes ping...
  2. Permissions across different domains: I had problems some sprints ago with this, the reason was permissions. My testing local machine was in a different domain than the server. Check that thor and your machine are in the same domain. Is possible to have it accross domains, but I could not have it working (so I moved my tests to a machine in the same domain)
  3. Queue tool: Although you can see queues from Administrative tools I found Queue explorer tool (http://cogin.com/mq/index.php) pretty useful. You can check where are the messages getting stuck.

NOTE: probably 1 is ok, but just in the case I put it...

Necessary answered 6/10, 2010 at 12:22 Comment(0)
A
0

You need to use the MsmqIntegrationBinding. The messages are not being recognized and are getting discarded since WCF doesn't know what they are.

Allegra answered 11/10, 2010 at 16:20 Comment(2)
I thought MsmqIntegrationBinding was for intercommunication between WCF apps and non-WCF apps. The example code where I manually added something to the queue was just to show that it wasn't a simple "turn off your firewall" issue. In production the queue will only be accessed by WCF services.React
My apologies, my eyes skipped by the 2nd client. Is the client an XP machine? We've had Kerberos trouble with XP. There is a patch for it.Allegra

© 2022 - 2024 — McMap. All rights reserved.