wcfmsmqnetmsmqbinding

Can't get service to pull from (dead letter) queue


I have a queue named log on a remote machine. When I call that queue locally, I specify a custom dead-letter queue by modifying my NetMsmqBinding:

_binding.DeadLetterQueue = DeadLetterQueue.Custom;
_binding.CustomDeadLetterQueue = new Uri(
    "net.msmq://localhost/private/Services/Logging/LogDeadLetterService.svc");

This works fine; when I force my message to fail to get to its destination, it appears in this queue.

Now, I have a service hosted in IIS/WAS to read the dead-letter queue. It it hosted in a site called Services, at Services/Logging/LogDeadLetterService.svc. Here's the service in my config:

  <service name="Me.Logging.Service.LoggingDeadLetterService">
    <endpoint binding="netMsmqBinding"
              bindingNamespace="http://me.logging/services/2012/11"
              contract="Me.Logging.Service.Shared.Service.Contracts.ILog" />
  </service>

And here's my activation:

    <add relativeAddress="LogDeadLetterService.svc"
         service="Me.Logging.Service.LoggingDeadLetterService" />

My actual service is basically this:

[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any, // Pick up any messages, regardless of To address.
                 InstanceContextMode = InstanceContextMode.Single, // Singleton instance of this class.
                 ConcurrencyMode = ConcurrencyMode.Multiple, // Multiple callers at a time.
                 Namespace = "http://me.logging/services/2012/11")]
public class LoggingDeadLetterService : ILog
{
    public void LogApplication(ApplicationLog entry)
    {
        LogToEventLog(entry);
    }
}

My queue is transactional and authenticated. I have net.msmq included as enabled protocols both on the Services site and on the Logging application, and I added a net.msmq binding to the Services site. If I have the binding information as appdev.me.com, I get the following error when browsing to http://appdev.me.com/Logging/LogDeadLetterService.svc (appdev.me.com is setup in my HOSTS file):

An error occurred while opening the queue:Access is denied. (-1072824283, 0xc00e0025).

If I have the binding information as localhost, I get the following error:

An error occurred while opening the queue:The queue does not exist or you do not have sufficient permissions to perform the operation. (-1072824317, 0xc00e0003).

No matter which way I have it set up, the service isn't picking up the dead letter, as it's still in the queue and not in my event log.

Now, I realize that both of these reference a permissions issue. However, in the interest of getting the code part of this tested before figuring out the authentication piece, I have given Full Control to everyone I could think of - to include Everyone, Authenticated Users, NETWORK SERVICE, IIS_USERS, ANONYMOUS LOGON, and myself. (The app pool is running as me.)

Any help as to how to get my service to be able to pull from this queue would be phenomenal. Thanks!

EDIT: According to this MSDN blog entry, 0xC00E0003 corresponds to MQ_ERROR_QUEUE_NOT_FOUND, and 0xc00e0025 corresponds to MQ_ERROR_ACCESS_DENIED, so it looks like I want to have the binding information as appdev.me.com. However, that still doesn't resolve the apparent permissions issue occurring.

EDIT2: It works if I host the service in a console app and provide the following endpoint:

    <endpoint address="net.msmq://localhost/private/Services/Logging/LogDeadLetterService.svc"
              binding="netMsmqBinding"
              bindingNamespace="http://me.logging/services/2012/11"
              contract="Me.Logging.Service.Shared.Service.Contracts.ILog" />

So what's going on differently in the console app than is going on in IIS? I'm pretty confident, due to EDIT above, that I'm hitting the queue. So why can't I get into it?

EDIT3: Changed Services/Logging/LogDeadLetterService.svc to Logging/LogDeadLetterService.svc per the advice given here, but no change.

//

[Bonus question: Do I need to handle poison messages in my dead letter queue?]


Solution

  • So, three things needed to be changed:

    1. The binding does have to be localhost.
    2. The queue has to be named Logging/LogDeadLetterService.svc to be found - it's the application and the service, not the site, application, and service.
    3. I had something messed up with the application pool - I have no idea what it was, but using a different app pool worked, so I backed out all of my service-related changes and then recreated everything, and it works.

    Well, that was a lot of banging my head against my desk for something as simple as "don't mess up your app pool."