IIS中的WCF,在工作组模式下使用MSMQ

时间:2010-12-20 19:42:31

标签: c# wcf iis msmq

我一直在尝试使用WCF进行MSMQ,但我似乎无法让它正常工作。通过使用WCF和服务引用,我得到了客户端(它向队列发送消息)。执行此操作的代码或多或少是这样的:

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

当我添加服务引用时,MsmqContractClient是由visual studio生成的代理。 app.config中的端点指向msmqueue:

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

这很有效,消息正在发布到队列中。

现在我试图让服务真正起作用,但我一直收到这个错误:

  

绑定验证失败,因为   绑定的MsmqAuthenticationMode   property设置为WindowsDomain但是   MSMQ与Active一起安装   目录集成已禁用。该   渠道工厂或服务主机不能   被打开了。

我尝试过的事情是:

  • 授予每个人对队列的完全访问权限(包括匿名登录)

  • 使用以下命令配置应用程序以使用配置文件中的特定绑定:

    <bindings>
      <netMsmqBinding>
         <binding name="MsmqBindingNonTransactionalNoSecurity" 
                  deadLetterQueue="Custom" 
                  exactlyOnce="false">
           <security mode="None" />
         </binding>
      </netMsmqBinding>
    </bindings>
    
  • 我尝试在自己的帐户和管理员帐户下运行IIS(7)中的应用程序池

让我感到困惑的是,它一直试图说服我,我正在尝试使用WindowsDomain身份验证来运行它。我声明我不想在安全模式设置为none的情况下这样做,对吗?

我的应用程序目前只是一个添加了WCF服务的webforms asp.net网站。

如果有人能够至少指出我正确的方向,我会非常感激,因为我已经花了太多时间在这上面。


似乎忽略或覆盖了配置。完整的错误消息:

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

我试图搞清楚使用Reflector会发生什么,但它似乎只是某种方式将MsmqTransportBindingElement传递到通道构建过程中,它确信它必须使用WindowsDomain作为安全措施。但是,我的配置文件中的安全性设置为none。关于这种覆盖行为来自哪里的任何想法?


分辨率:

一方面我觉得自己很傻,但另一方面我觉得还有改进的余地。 简短的版本是我搞砸了服务元素的'name'属性中的值:

<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>

该名称与我的客户端相同,但客户端具有visual studio生成的绑定。我给它一个不同的名称(MsmqService),因此名称值为'MsmqService.MsmqService'。

让我感到困扰的是,我没有得到任何关于我正在配置不存在的服务的警告,或者我正在使用服务的默认配置的任何指示。如果框架至少会在我使用默认值的地方生成警告,或者打开某种形式的严格模式的选项,那将是非常好的。无论哪种方式,感谢您的所有投入,我将再次撞到墙上几次。

是的,你现在可以指点笑; - )

4 个答案:

答案 0 :(得分:9)

尝试这些设置... useActiveDirectory默认情况下应该为false,但请尝试一下。身份验证模式在传输本身上设置,因此msmqAuthenticationMode应设置为“none”。 msmqProtectionLevelclientCredentialType听起来很相关,所以我把它们扔进去了 :)


<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>

我会担心删除所有安全性,但是......如果您在域中,则应安装MSMQ和Active Directory集成,或使用工作组方法保护消息。

另外,请不要忘记,服务器和客户端的设置必须匹配。

HTH,
詹姆斯

对于不断更新,我今天对细节的关注似乎有点低 :P

答案 1 :(得分:2)

不确定这是否能解决您的具体问题,但汤姆·霍兰德有一篇非常好的三篇博文系列文章:

此外,由于Active Directory的问题似乎是问题所在,您是否试图告诉您的MSMQ绑定不使用AD?

<bindings>
  <netMsmqBinding>
     <binding name="MsmqBindingNonTransactionalNoSecurity" 
              deadLetterQueue="Custom" exactlyOnce="false"
              useActiveDirectory="false">   <== try this setting here!
        <security mode="None" />
     </binding>
  </netMsmqBinding>
</bindings>

答案 2 :(得分:2)

当我们遇到这个问题时 <security mode="None">在测试环境中工作。

在最终交付期间,即使这不起作用..最后这个工作

<security>
<transport
msmqAuthenticationMode="None"
msmqProtectionLevel="None"/>
</security>

答案 3 :(得分:1)

Dennis van der Stelt在WCF + MSMQ上提供了一个很好的示例。

您可能也对MSDN上的此问答感兴趣:

  

问:当我运行在工作组模式下使用默认绑定的示例时,消息似乎已发送但接收器从未接收过。

     

答:默认情况下,使用需要Active Directory目录服务的MSMQ内部证书对邮件进行签名。在工作组模式下,由于Active Directory不可用,因此对邮件进行签名失败。因此,消息落在死信队列中,并指示失败原因,例如“错误签名”。

     

解决方法是关闭安全性。这可以通过设置Mode = None来使其在工作组模式下工作。

     

另一种解决方法是从Transport属性获取MsmqTransportSecurity并将其设置为Certificate,并设置客户端证书。

     

另一种解决方法是使用Active Directory集成安装MSMQ。