none
WCF Routing IRequestReplyRouter basicHttpBinding -> Error: Contract requires Session RRS feed

  • Question

  • Hello,

    I tried creating a routing service in WCF. My aim is bridging protocols (or rather authentication) in the end, but I started with plain basicHttpBinding for the routing service and the service to get it routed, too. I used a binding config in both cases as I have to make some adjustments (not done at the moment). It is no option to use wsHttpBinding for the routing service, as the client is not capable of it.

    The routing service is hosted in IIS. When I try opening the svc in the browser I get the following error:

    "Contract requires Session, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it. "

    I only have an svc file and a web.config which should be enough.

    The svc:

    <%@ ServiceHost Language="C#" Debug="true" Service="System.ServiceModel.Routing.RoutingService, System.ServiceModel.Routing, version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"  %>
    

    The web.config:

    <?xml version="1.0"?>
    <configuration>
      <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
      </appSettings>
      <system.web>
        <compilation debug="false" targetFramework="4.5">
          <assemblies>
            <add assembly="System.ServiceModel.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
          </assemblies>
        </compilation>
        <httpRuntime targetFramework="4.5"/>
      </system.web>
      <system.serviceModel>
        <services>
          <service name="MyRoutingService" behaviorConfiguration="MyRoutingServiceBehavior">
            <endpoint name="RequestReplyBindingEP" address="" binding="basicHttpBinding"  contract="System.ServiceModel.Routing.IRequestReplyRouter" bindingConfiguration="MyRoutingSvcBasicHttpBinding" />
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="MyRoutingServiceBehavior">
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
              <routing filterTableName="routingFilterTable" routeOnHeadersOnly="false"/>
            </behavior>
          </serviceBehaviors>
          <endpointBehaviors>
            <behavior name="MySvcBehavior">
              <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
            </behavior>
          </endpointBehaviors>
        </behaviors>
        <bindings>
          <basicHttpBinding>
            <binding name="MySvcBasicHttpBinding" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="false">
              <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
              <security mode="Transport">
                <transport clientCredentialType="Windows" proxyCredentialType="None" realm=""/>
              </security>
            </binding>
            <binding name="MyRoutingSvcBasicHttpBinding" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="false">
              <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
              <security mode="None">
                <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
              </security>
            </binding>
          </basicHttpBinding>
        </bindings>
        <client>
          <endpoint name="MySvcBasicHttpEndpoint" behaviorConfiguration="MySvcBehavior" binding="basicHttpBinding" bindingConfiguration="MySvcBasicHttpBinding" contract="Contract.IMyService" address="https://somehost/MyService/2.0/MyService.svc"/>
        </client>
        <routing>
          <filters>
            <filter name="EPAddressFilter" filterType="EndpointName" filterData="RequestReplyBindingEP"/>
          </filters>
          <filterTables>
            <filterTable name="routingFilterTable">
              <add filterName="EPAddressFilter" endpointName="MySvcBasicHttpEndpoint"/>
            </filterTable>
          </filterTables>
        </routing>
        <protocolMapping>
          <add binding="basicHttpBinding" scheme="http"/>
        </protocolMapping>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
      <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"  />
        <directoryBrowse enabled="true"/>
      </system.webServer>
    </configuration>
    I tried some of the stuff I read on the web (like throwing out the aspcompatibility)

    So far I was not able to find help. Does anyone have an idea? I am not able to spot what I am missing here...

    Thank you very much in advance!

    Marc

    Monday, February 24, 2014 2:48 PM

Answers

  • Ok Marc, I understand what you are trying to achieve and I have seen this work before when bridging between legacy applications and new services.  At the time a new wcf service was introduced so not exactly what you want to achieve.

    I am not sure off-hand but I suspect it is the RoutingService and not the IRequestReplyRouter.

    [AspNetCompatibilityRequirementsAttribute(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehaviorAttribute(AddressFilterMode = AddressFilterMode.Any, InstanceContextMode = InstanceContextMode.PerSession, 
    	UseSynchronizationContext = false, ValidateMustUnderstand = false)]
    public sealed class RoutingService : ISimplexDatagramRouter, 
    	ISimplexSessionRouter, IRequestReplyRouter, IDuplexSessionRouter, IDisposable
    I don't think you can do what you are trying to achieve without creating your own implementation of RoutingService that only supports IRequestReplyRouter.

    Sorry to not be able to help.  At least you have standing up a proxy-like service to fall back on...

    Cheers,


    Jeff

    • Marked as answer by Marc Ipsen Wednesday, February 26, 2014 6:40 AM
    Tuesday, February 25, 2014 9:55 PM

All replies

  • Hello Marc,

    Off-hand the WCF basichttp will not support what you want to do: http://sankarsan.wordpress.com/2008/09/07/wcf-sessions/http://msdn.microsoft.com/en-us/library/ms733058(v=vs.110).aspx

    But, maybe there is another way.  You say you want to have a routing service primarily for authentication and your client does not support wshttp.  My guess is the client is not one you control (re., develop) and/or it is Java based.  Is this true?  My guess is you control the downstream resource that is being accessed and the IIS service that will be used for routing.  

    Can you confirm/correct my guesses?  Worst case scenario is you could build your service to support a form of token exchange.  For example, an operation to authenticate and return a temp token with a x number of minute expiry.  This then is sent to another operation that exposes the functionality you want (MySvcBasicHttpEndpoint).  This gets messy if your scenario is more complex (e.g., load balanced).


    Jeff

    Monday, February 24, 2014 8:14 PM
  • Hi Jeff,

    thank you very much for helping.

    To clear up things:

    The client (far older tech. than JAVA... ;-)) has to make calls to different services in the network (mostly request-response, some one-way). None of the services to be called use any session or duplex stuff whatsoever and have nothing like it defined in the contracts, so I guess it might be necessary for WCF routing? I was not able to find any notion about that, apart from IRequestReplyRouter is able to support sessions, but does not require them. So I suspect, that I maybe made mistake configuring routing?

    The technology of the client only allows SOAP 1.1 with Basic Auth. or Anonymous, nothing else. We have a strict policy that services may only be called using Certificate Auth. So the idea was to use a WCF routing service which should reside on the machine where the client lives(at least it is a  Windows Server 2008 R2...), call the WCF routing service using Basic Auth. and route the calls to the services on the network using the machine's certificate.

    We planned to use WCF routing to save the effort of writing a "real" service to bridge this.

    I hope this helps to get a better picture? If there are more questions, please feel free to ask!

    Marc


    • Edited by Marc Ipsen Tuesday, February 25, 2014 5:31 AM
    Tuesday, February 25, 2014 5:30 AM
  • Ok Marc, I understand what you are trying to achieve and I have seen this work before when bridging between legacy applications and new services.  At the time a new wcf service was introduced so not exactly what you want to achieve.

    I am not sure off-hand but I suspect it is the RoutingService and not the IRequestReplyRouter.

    [AspNetCompatibilityRequirementsAttribute(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehaviorAttribute(AddressFilterMode = AddressFilterMode.Any, InstanceContextMode = InstanceContextMode.PerSession, 
    	UseSynchronizationContext = false, ValidateMustUnderstand = false)]
    public sealed class RoutingService : ISimplexDatagramRouter, 
    	ISimplexSessionRouter, IRequestReplyRouter, IDuplexSessionRouter, IDisposable
    I don't think you can do what you are trying to achieve without creating your own implementation of RoutingService that only supports IRequestReplyRouter.

    Sorry to not be able to help.  At least you have standing up a proxy-like service to fall back on...

    Cheers,


    Jeff

    • Marked as answer by Marc Ipsen Wednesday, February 26, 2014 6:40 AM
    Tuesday, February 25, 2014 9:55 PM
  • Hi Jeff,

    thank you for your effort. It not quite the answer I liked to hear but at least I know now, that I don't have to try and follow that direction any more. I will create our own special routing service.

    Best regards

    Marc

    Wednesday, February 26, 2014 6:41 AM