Получение ошибки при использовании маршрутизации URL-адресов со встроенной службой маршрутизатора WCF

Я хотел создать конечную точку маршрутизатора без расширения (если возможно, без файлов) через службу маршрутизатора WCF, которая имеет политику безопасности пользователя/пароля клиента. Я получаю следующее исключение ошибки при попытке маршрутизировать сообщения SOAP через него:

<s:Fault>
     <faultcode xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:InternalServiceFault</faultcode>
     <faultstring xml:lang="en-US">An unexpected failure occurred. Applications should not attempt to handle this error. For diagnostic purposes, this English message is associated with the failure: 'Shouldn't allocate SessionChannels if session-less and impersonating'.</faultstring>
     <detail>
        <ExceptionDetail xmlns="http://schemas.datacontract.org/2004/07/System.ServiceModel" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
           <HelpLink i:nil="true"/>
           <InnerException i:nil="true"/>
           <Message>An unexpected failure occurred. Applications should not attempt to handle this error. For diagnostic purposes, this English message is associated with the failure: 'Shouldn't allocate SessionChannels if session-less and impersonating'.</Message>
           <StackTrace>at System.Runtime.Fx.AssertAndThrow(String description)   
at  System.ServiceModel.Routing.RoutingChannelExtension.get_SessionChannels()
at System.ServiceModel.Routing.RoutingService.GetOrCreateClient[TContract](RoutingEndpointTrait endpointTrait, Boolean impersonating)
at System.ServiceModel.Routing.ProcessRequestAsyncResult`1.StartProcessing()
at System.ServiceModel.Routing.ProcessRequestAsyncResult`1..ctor(RoutingService service, Message message, AsyncCallback callback, Object state)
at System.ServiceModel.Routing.RoutingService.BeginProcessRequest[TContract](Message message, AsyncCallback callback, Object state)
at System.ServiceModel.Routing.RoutingService.System.ServiceModel.Routing.IRequestReplyRouter.BeginProcessRequest(Message message, AsyncCallback callback, Object state)
at AsyncInvokeBeginBeginProcessRequest(Object , Object[] , AsyncCallback , Object )
at System.ServiceModel.Dispatcher.AsyncMethodInvoker.InvokeBegin(Object instance, Object[] inputs, AsyncCallback callback, Object state)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&amp; rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&amp; rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc&amp; rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</StackTrace>
           <Type>System.Runtime.Fx+InternalException</Type>
        </ExceptionDetail>
     </detail>
  </s:Fault>

Мне пришлось включить AspNetCompability для хоста службы из-за маршрутизации URL-адресов.
Вот шаги, которые я выполнил:
Я настроил базовое веб-приложение .net 4.0 с соответствующими правилами маршрутизации URL-адресов в RouteTable:

routes.Add(new ServiceRoute("routerservice", new CustomServiceHostFactory(), typeof(System.ServiceModel.Routing.RoutingService)));` 

Мой код CustomServiceHostFactory:

public class CustomServiceHostFactory : ServiceHostFactory
{
    protected override System.ServiceModel.ServiceHost CreateServiceHost(System.Type serviceType, System.Uri[] baseAddresses)
    {
        var host = base.CreateServiceHost(serviceType, baseAddresses);

        var aspnet = host.Description.Behaviors.Find<AspNetCompatibilityRequirementsAttribute>();

        if (aspnet == null)
        {
            aspnet = new AspNetCompatibilityRequirementsAttribute();
            host.Description.Behaviors.Add(aspnet);
        }

        aspnet.RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed;

        return host;
    }
}

В файле web.config я определяю конечную точку службы и поведение:

<services>
  <service name="System.ServiceModel.Routing.RoutingService" behaviorConfiguration="GatewayServiceBehavior">
    <endpoint address="" binding="basicHttpBinding" contract="System.ServiceModel.Routing.IRequestReplyRouter" bindingConfiguration="GatewaySecureBinding" />
  </service>
</services>

Конфигурации привязки и поведения просты, требуется всего лишь простая проверка имени пользователя/пароля:

<binding name="GatewaySecureBinding" closeTimeout="00:01:00"
      openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
      allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
      maxBufferPoolSize="524288" maxBufferSize="65536" maxReceivedMessageSize="65536"
      textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true"
      messageEncoding="Mtom">
      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
      <security mode="TransportWithMessageCredential">
        <transport clientCredentialType="None" proxyCredentialType="None"
          realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
    </binding>

<behavior name="GatewayServiceBehavior">        
      <serviceCredentials>
        <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="CustomLib.CustomUsernameValidator, CustomLib"/>
      </serviceCredentials>
      <routing filterTableName="RoutingTable1" routeOnHeadersOnly="true"/>

      <serviceDebug includeExceptionDetailInFaults="true"/>
    </behavior>  

person Roman    schedule 30.05.2013    source источник
comment
Согласно этому сообщению в блоге - seroter.wordpress.com/2010/09/19/ - BasicHttpBinding и совместимость с aspnet не очень хорошо сочетаются в этом сценарии.   -  person Tim    schedule 30.05.2013
comment
Да, я видел несколько сообщений по этой проблеме без четкого ответа, поэтому в итоге я создал этот вопрос. wsHttpBinding не подходит, так как это внешняя веб-служба. Меня бы озадачило, если бы служба маршрутизации WCF в целом не работала с basicHttpBinding. Это ограничило бы его использование.   -  person Roman    schedule 30.05.2013
comment
Почему вы считаете, что wsHttpBinding не вариант? Его может использовать с внешними веб-сервисами. Он поддерживает SOAP 1.2 и спецификации ws-*. Если вам нужно поддерживать только SOAP 1.1, тогда да, вы ограничены basicHttpBinding (или переносом собственной привязки).   -  person Tim    schedule 30.05.2013
comment
wsHttpBinding интегрирован для использования учетных данных Windows по умолчанию для обеспечения безопасности. Мне нужна возможность маршрутизировать либо анонимно, либо через имя пользователя/пароль из БД. Возможно, я не знаю, как перенастроить wsHttpBinding для поддержки обоих сценариев.   -  person Roman    schedule 30.05.2013