WCF в IIS, используя MSMQ в режиме рабочей группы

Я пробовал использовать 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».

Что меня беспокоит, так это то, что я не получил никаких предупреждений о том, что я настраиваю несуществующую службу, или каких-либо указаний на то, что я использую конфигурацию по умолчанию для службы. Было бы действительно хорошо, если бы фреймворк хотя бы генерировал где-нибудь предупреждение о том, что я использую значения по умолчанию, или возможность включить какую-либо форму строгого режима. В любом случае, спасибо за ваш вклад, и я собираюсь биться головой о стену еще несколько раз.

И да, теперь вы можете указать и посмеяться ;-)


person Erik van Brakel    schedule 20.12.2010    source источник
comment
Вы легенда! Я проливал свой конфиг уже несколько часов и только что понял, что совершил ту же ошибку, что и вы!   -  person Darren Lewis    schedule 18.11.2011
comment
Ха-ха, спасибо, что я облажался и выяснил свою ошибку, и это помогло другому разработчику :)   -  person Erik van Brakel    schedule 18.11.2011
comment
бился головой о стену, пока не нашел это. Есть ли хоть какая-то связь между реальной проблемой и сообщением об ошибке ...   -  person ravi    schedule 23.04.2012
comment
У меня тоже была такая же проблема. Не понял, что мое имя службы было неправильным, что привело к этой вводящей в заблуждение ошибке! +1   -  person ajawad987    schedule 14.09.2012


Ответы (4)


Попробуйте эти настройки ... useActiveDirectory по умолчанию должно быть false, но попробуйте. Режим аутентификации устанавливается на самом транспорте, поэтому для msmqAuthenticationMode следует установить значение «none». msmqProtectionLevel и clientCredentialType звучат уместно, поэтому я тоже их туда добавила
:)


<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

person James King    schedule 27.12.2010
comment
Конечно, я согласен с тем, что удаление всей безопасности нехорошо в производственной среде. Но для простой демонстрации работы этой штуки мне нужно, чтобы она работала как можно проще. Сейчас попробую ваши настройки. - person Erik van Brakel; 28.12.2010
comment
Хм, все равно не работает. Собираюсь попробовать на другой машине, может быть, это моя среда. +1 за упоминание о безопасности должно быть отключено ;-) - person Erik van Brakel; 28.12.2010
comment
Чтобы найти это, пришлось долго копать, но схему netMsmqBinding можно найти здесь: msdn.microsoft.com/en-us/library/ms731380.aspx - person James King; 28.12.2010
comment
Хм, а можно выложить свои полные конфигурации клиента и сервера? - person James King; 28.12.2010
comment
Также попробуйте изменить ‹security mode = None› на просто ‹security›. «Транспортная» безопасность по умолчанию ... может быть, если она не установлена, она игнорирует транспортную конфигурацию? - person James King; 28.12.2010
comment
Это всего лишь полные конфигурации клиента и сервера. Ни больше ни меньше. Еще одно дополнение: это начинает появляться, когда я добавляю привязку net.msmq к моему приложению в IIS. Когда это только http, он не терпит неудачу. - person Erik van Brakel; 28.12.2010
comment
Принимаю твой ответ. В конечном итоге это БЫЛА проблема с конфигурацией (см. Решение в вопросе) - person Erik van Brakel; 28.12.2010
comment
Это ОЧЕНЬ странная ошибка для проблемы с пространством имен. Я не знал, что VS может создать привязки для несуществующей службы. - person James King; 29.12.2010
comment
clientCredentialType = None теперь не может быть установлен в .NET 4.5.1 - person huoxudong125; 15.10.2015

Не уверен, что это решит вашу конкретную проблему, но есть действительно хорошая серия сообщений в блоге Тома Холландера из трех частей:

Кроме того, поскольку проблема, по-видимому, связана с 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>
person marc_s    schedule 20.12.2010
comment
Обновленные ссылки: часть 1, dzone.com/articles/msmq-wcf -and-iis-getting-them- Часть 2, dzone.com/articles/msmq-wcf-and-iis-getting-them--0 Часть 3, dzone.com/articles/msmq-wcf-and-iis-getting-them--1 - person user2986756; 09.02.2021

Когда мы столкнулись с проблемой, <security mode="None"> работал в тестовой среде.

Во время окончательной доставки даже это не сработало .. Наконец то сработало

<security>
<transport
msmqAuthenticationMode="None"
msmqProtectionLevel="None"/>
</security>
person Ananth    schedule 15.06.2012

Деннис ван дер Стелт предоставил хороший образец на WCF + MSMQ.

Вас также может заинтересовать этот вопрос / ответ на странице MSDN:

Q: Когда я запускаю образец, который использует привязку по умолчанию в режиме рабочей группы, сообщения кажутся отправленными, но никогда не принимаются получателем.

О: По умолчанию сообщения подписываются с помощью внутреннего сертификата MSMQ, для которого требуется служба каталогов Active Directory. В режиме рабочей группы, поскольку Active Directory недоступен, подписание сообщения не выполняется. Таким образом, сообщение попадает в очередь недоставленных сообщений и указывается причина сбоя, например «Плохая подпись».

Обходной путь - отключить безопасность. Это делается установкой Mode = None, чтобы он работал в режиме рабочей группы.

Другой обходной путь - получить MsmqTransportSecurity из свойства Transport, установить для него значение Certificate и установить сертификат клиента.

Еще один обходной путь - установить MSMQ с интеграцией Active Directory.

person Sam B    schedule 20.12.2010
comment
Я использую его сейчас, просто отправляя что-то на сервер. Эта часть работает нормально, сообщения попадают в очередь (а не в очередь недоставленных). - person Erik van Brakel; 20.12.2010