3

I wanted to create an extension less (file-less if possible) router endpoint via WCF Router Service that has customer user/password security policy. I am getting the following Fault Exception when attempting to route SOAP messages through it:

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

I did have to enabled AspNetCompability for the service host due to URL Routing.
Here are the steps that I followed:
I have set up a basic .net 4.0 web application with appropriate URL routing rules in RouteTable:

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

My CustomServiceHostFactory code:

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

In web.config file I define the service endpoint and behavior:

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

The binding and behavior configurations are straight forward with just a simple username/password validation requirement:

<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>  
Roman
  • 1,177
  • 1
  • 17
  • 25
  • 4
    According to this blog post - http://seroter.wordpress.com/2010/09/19/lesson-learned-wcf-routing-service-and-the-basichttpbinding/ - `BasicHttpBinding` and aspnet compatability don't play nicely together in this scenario. – Tim May 30 '13 at 05:24
  • Yeah, i saw a few posts regarding this issue with no clear answer, therefore I ended up creating this question. wsHttpBinding is not an option as it is an externally facing web service. I'd find it perplexing if WCF Routing Service does not work well in general with basicHttpBinding. That would limit its use. – Roman May 30 '13 at 17:25
  • Why do you feel `wsHttpBinding` is not an option? It *can* be used with external web serivces. It supports SOAP 1.2 and the ws-* specifications. If you need to support only SOAP 1.1 then yes, you're limited to `basicHttpBinding` (or rolling your own binding). – Tim May 30 '13 at 17:30
  • wsHttpBinding is integrated to use Windows credentials by default for security. I need the ability to route either anonymously or via username/password from db. I might not know how to reconfigure wsHttpBinding to support both scenarios. – Roman May 30 '13 at 17:51

0 Answers0