C# – WCF in IIS, using MSMQ in workgroup mode

ciismsmqwcf

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 😉

Best Answer

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

Related Topic