我一直在尝试使用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属性设置为WindowsDomain,但MSMQ已安装并禁用了Active Directory集成。 通道工厂或服务主机无法打开。
我尝试过的方法有:
赋予每个人(包括匿名登录)对队列的完全访问权限
使用以下内容从配置文件中配置应用程序以使用特定绑定:
我尝试在IIS(7)中使用我的账户和管理员账户运行应用程序池,但是它一直试图让我相信我正在尝试使用WindowsDomain身份验证来运行它。 我已经将安全模式设置为none,并声明了我不想这样做,这让我困扰不已。<bindings> <netMsmqBinding> <binding name="MsmqBindingNonTransactionalNoSecurity" deadLetterQueue="Custom" exactlyOnce="false"> <security mode="None" /> </binding> </netMsmqBinding> </bindings>
目前,我的应用程序只是一个添加了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”。
令我有些困扰的是,我没有收到任何关于我正在配置不存在的服务或者我正在使用服务默认配置的表示。如果框架至少能够在某处生成警告表明我正在使用默认设置,或提供打开某种形式的严格模式的选项,那将会非常好。无论如何,感谢您提供的所有信息,我还要再撞墙几次。
是的,你现在可以指着我笑了;-)