WCF in IIS, using MSMQ in workgroup mode
Asked Answered
D

4

13

I've been trying out MSMQ with WCF, but I can't seem to get it to work properly. I've got the client (which sends messages to the queue) working, by using WCF and a service reference. The code that does this is more or less this:

static void Main(string[] args)
{
    var client = new MsmqServiceReference.MsmqContractClient();
    client.SendMessage("TEST");
    client.Close();
    Console.ReadKey();
}

Where MsmqContractClient is a proxy generated by visual studio when I add a service reference. The endpoint in the app.config is pointing to a msmqueue:

<client>
  <endpoint 
    address="net.msmq://localhost/private/MsmqService/MsmqService.svc"
    binding="netMsmqBinding"  
    bindingConfiguration="MsmqBindingNonTransactionalNoSecurity"
    contract="MsmqServiceReference.IMsmqContract" name="MsmqService" />
</client>

This works, messages are being posted to the queue.

Now I am trying to actually get the service to work, but I keep getting this error:

Binding validation failed because the binding's MsmqAuthenticationMode property is set to WindowsDomain but MSMQ is installed with Active Directory integration disabled. The channel factory or service host cannot be opened.

Things I've tried are:

  • give everyone full access (including anonymous logon) to the queue

  • configuring the app to use a specific binding from the config file using:

    <bindings>
      <netMsmqBinding>
         <binding name="MsmqBindingNonTransactionalNoSecurity" 
                  deadLetterQueue="Custom" 
                  exactlyOnce="false">
           <security mode="None" />
         </binding>
      </netMsmqBinding>
    </bindings>
    
  • I tried running the app pool in IIS (7) under my own account and administrator account

What stumps me is that it keeps trying to convince me that I am trying to run it with WindowsDomain authentication. I stated that I DIDN'T want to do that with the security mode set to none, right?

My app at the moment is simply a webforms asp.net site with a WCF service added to it.

If someone could at least point me into the right direction I'll be very grateful, as I've spent too much time on this already.


It seems as if the configuration is being ignored, or overridden. The full error message:

WebHost failed to process a request.
 Sender Information: System.ServiceModel.Activation.HostedHttpRequestAsyncResult/63721755
 Exception: System.ServiceModel.ServiceActivationException: The service '/MsmqService/MsmqService.svc' cannot be activated due to an exception during compilation.  The exception message is: Binding validation failed because the binding's MsmqAuthenticationMode property is set to WindowsDomain but MSMQ is installed with Active Directory integration disabled. The channel factory or service host cannot be opened.. ---> System.InvalidOperationException: Binding validation failed because the binding's MsmqAuthenticationMode property is set to WindowsDomain but MSMQ is installed with Active Directory integration disabled. The channel factory or service host cannot be opened.
   at System.ServiceModel.Channels.MsmqVerifier.VerifySecurity(MsmqTransportSecurity security, Nullable`1 useActiveDirectory)
   at System.ServiceModel.Channels.MsmqVerifier.VerifyReceiver(MsmqReceiveParameters receiveParameters, Uri listenUri)
   at System.ServiceModel.Channels.MsmqTransportBindingElement.BuildChannelListener[TChannel](BindingContext context)
   at System.ServiceModel.Channels.BindingContext.BuildInnerChannelListener[TChannel]()
   at System.ServiceModel.Channels.MessageEncodingBindingElement.InternalBuildChannelListener[TChannel](BindingContext context)
   at System.ServiceModel.Channels.BinaryMessageEncodingBindingElement.BuildChannelListener[TChannel](BindingContext context)
   at System.ServiceModel.Channels.BindingContext.BuildInnerChannelListener[TChannel]()
   at System.ServiceModel.Channels.Binding.BuildChannelListener[TChannel](Uri listenUriBaseAddress, String listenUriRelativeAddress, ListenUriMode listenUriMode, BindingParameterCollection parameters)
   at System.ServiceModel.Description.DispatcherBuilder.MaybeCreateListener(Boolean actuallyCreate, Type[] supportedChannels, Binding binding, BindingParameterCollection parameters, Uri listenUriBaseAddress, String listenUriRelativeAddress, ListenUriMode listenUriMode, ServiceThrottle throttle, IChannelListener& result, Boolean supportContextSession)
   at System.ServiceModel.Description.DispatcherBuilder.BuildChannelListener(StuffPerListenUriInfo stuff, ServiceHostBase serviceHost, Uri listenUri, ListenUriMode listenUriMode, Boolean supportContextSession, IChannelListener& result)
   at System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost)
   at System.ServiceModel.ServiceHostBase.InitializeRuntime()
   at System.ServiceModel.ServiceHostBase.OnBeginOpen()
   at System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout)
   at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
   at System.ServiceModel.Channels.CommunicationObject.Open()
   at System.ServiceModel.ServiceHostingEnvironment.HostingManager.ActivateService(String normalizedVirtualPath)
   at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath)
   --- End of inner exception stack trace ---
   at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
   at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result)
 Process Name: w3wp
 Process ID: 5660

I tried figuring out what happens using Reflector, but it simply seems that somehow a MsmqTransportBindingElement is passed into the channel building process, which is convinced it has to use WindowsDomain as a security measure. However, I have security set to none in my config file. Any ideas on where this override behavior comes from?


Resolution:

I feel really stupid on one hand, but I feel there's room for improvement on the other hand. The short version is that I messed up the value in the 'name' attribute on the service element:

<services>
  <service name="WcfService.MsmqService">
    <!--        <endpoint binding="mexHttpBinding" contract="IMetadataExchange" />-->
    <endpoint name="msmq" 
            address="net.msmq://localhost/private/MsmqService/MsmqService.svc"
            binding="netMsmqBinding" 
            bindingConfiguration="NoSecurity"
            contract="WcfService.IMsmqContract" />
  </service>
</services>

The name was the same as on my client, however, the client had bindings generated by visual studio. I gave it a different name (MsmqService), so the name value was 'MsmqService.MsmqService'.

What kinda bothers me is that I didn't get any warning whatsoever that I was configuring a non-existing service, or any indication I am using the default configuration for the service. It would be really nice if the framework would at least generate a warning somewhere that I am using defaults, or an option to turn on some form of strict mode. Either way, thanks for all your input, and I am going to bang my head against the wall a few more times.

And yes, you may now point and laugh ;-)

Darondarooge answered 20/12, 2010 at 19:42 Comment(4)
You are a legend! I've been pouring over my config for a few hours now and just realised I've made exactly the same mistake as you!Odetteodeum
Haha, thanks that my screwing up and figuring out my mistake has helped another fellow dev :)Darondarooge
banged my head against the wall, until I found this. Is there even any connection between the actual problem and the error message...Barsac
I also just had the same exact issue. Didn't realize my service name was incorrect, yielding this misleading error! +1Pickar
W
9

Try these settings... useActiveDirectory should be false by default, but try it. The authentication mode is set on the transport itself, so msmqAuthenticationMode should be set to 'none'. msmqProtectionLevel and clientCredentialType sound relevant, so I threw them in there, too
: )


<bindings>
  <netMsmqBinding>
     <binding name="MsmqBindingNonTransactionalNoSecurity" 
          deadLetterQueue="Custom"
          useActiveDirectory="false" 
          exactlyOnce="false">
       <security mode="None">
         <transport 
            msmqAuthenticationMode="None"
            msmqProtectionLevel="None"
            clientCredentialType="None"/>
       </security>
     </binding>
  </netMsmqBinding>
</bindings>

I'd be concerned about removing all the security, however... if you're on a domain, you should install MSMQ with Active Directory Integration, or use Workgroup methods of securing the messages.

Also, don't forget, the settings for the server and client have to match.

HTH,
James

Sorry for the continual updates, my attention to details seems to be a bit low today
: P

Whitford answered 27/12, 2010 at 21:1 Comment(9)
Of course, I agree that removing all security is not good on production environments. But for a simple demo of this thing working I need to have it running as simple as possible. Going to try out your settings now.Darondarooge
Hmm, still doesn't work. Going to try on a different machine, maybe it's my environment. +1 for mentioning security should be off though ;-)Darondarooge
Had to dig forever to find this, but the schema for netMsmqBinding can be found here: msdn.microsoft.com/en-us/library/ms731380.aspxWhitford
Hmm, can you post your full client and server configurations?Whitford
Also, try changing <security mode="None"> to just <security>. 'Transport' security is the default... maybe if it's set to none it's ignoring the transport configuration?Whitford
The full client and server configs are just that. Nothing more, nothing less. Another addition though, this starts showing up when I add the net.msmq binding to my app in IIS. When it's only http it doesn't fail.Darondarooge
Accepting your answer. It eventually WAS a config issue (see resolution on the question post)Darondarooge
That's a VERY strange error for a namespace issue. I didn't know it was possible to have VS generate bindings for a non-existent serviceWhitford
` clientCredentialType="None"` can't set now in .net 4.5.1Tardigrade
W
2

Not sure if this is going to solve your concrete problem here, but there's a really good three-part blog post series by Tom Hollander:

Also, since the Active Directory stuff seems to be the problem, have you tried to tell your MSMQ binding to not use AD ??

<bindings>
  <netMsmqBinding>
     <binding name="MsmqBindingNonTransactionalNoSecurity" 
              deadLetterQueue="Custom" exactlyOnce="false"
              useActiveDirectory="false">   <== try this setting here!
        <security mode="None" />
     </binding>
  </netMsmqBinding>
</bindings>
Word answered 20/12, 2010 at 20:21 Comment(1)
M
2

When we faced the issue <security mode="None"> worked in the test environment.

During final delivery , even that didn't work.. Finally this one worked

<security>
<transport
msmqAuthenticationMode="None"
msmqProtectionLevel="None"/>
</security>
Maltreat answered 15/6, 2012 at 4:19 Comment(0)
L
1

Dennis van der Stelt provide a good sample on WCF + MSMQ.

You may also be interested in this Q/A on MSDN:

Q: When I run the sample that uses a default binding in workgroup mode, messages seem to get sent but are never received by the receiver.

A: By default, messages are signed using an MSMQ internal certificate that requires the Active Directory directory service. In workgroup mode, because Active Directory is not available, signing the message fails. So the message lands in the dead-letter queue and failure cause, such as “Bad signature”, is indicated.

The workaround is to turn off security. This is done by setting Mode = None to make it work in workgroup mode.

Another workaround is to get the MsmqTransportSecurity from the Transport property and set it to Certificate, and set the client certificate.

Yet another workaround is to install MSMQ with Active Directory integration.

Lug answered 20/12, 2010 at 20:6 Comment(1)
The way I am using it now is basically send something to the server. That part works fine, the messages end up in the queue (and not the dead-letter one).Darondarooge

© 2022 - 2024 — McMap. All rights reserved.