Я пробовал использовать MSMQ с WCF, но не могу заставить его работать должным образом. У меня есть клиент (который отправляет сообщения в очередь) работает, используя 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. Невозможно открыть фабрику каналов или хост службы.
Вот что я пробовал:
предоставить всем полный доступ (включая анонимный вход) к очереди
настройка приложения для использования определенной привязки из файла конфигурации с помощью:
<bindings> <netMsmqBinding> <binding name="MsmqBindingNonTransactionalNoSecurity" deadLetterQueue="Custom" exactlyOnce="false"> <security mode="None" /> </binding> </netMsmqBinding> </bindings>
Я попытался запустить пул приложений в IIS (7) под своей учетной записью и учетной записью администратора.
Что меня озадачивает, так это то, что он пытается убедить меня, что я пытаюсь запустить его с аутентификацией WindowsDomain. Я заявил, что НЕ хочу этого делать с нулевым режимом безопасности, верно?
Мое приложение на данный момент представляет собой просто сайт asp.net webforms с добавленной к нему службой WCF.
Если бы кто-то мог хотя бы указать мне правильное направление, я был бы очень благодарен, так как я уже потратил на это слишком много времени.
Кажется, что конфигурация игнорируется или отменяется. Полное сообщение об ошибке:
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».
Что меня беспокоит, так это то, что я не получил никаких предупреждений о том, что я настраиваю несуществующую службу, или каких-либо указаний на то, что я использую конфигурацию по умолчанию для службы. Было бы действительно хорошо, если бы фреймворк хотя бы генерировал где-нибудь предупреждение о том, что я использую значения по умолчанию, или возможность включить какую-либо форму строгого режима. В любом случае, спасибо за ваш вклад, и я собираюсь биться головой о стену еще несколько раз.
И да, теперь вы можете указать и посмеяться ;-)