Saturday, June 30, 2018

Cannot support both http and https url when running a ServiceHost

Leave a Comment

I'm trying to enable exposing a ServiceHost on both HTTP & HTTPS.

Here is the code that runs the service:

oServiceHost = new ServiceHost(typeof(API), new Uri(WebHookURL)) oServiceHost.Open(); 

As you can see here - I'm getting the service URL (WebHookURL) during runtime. As mentioned, URL protocol can be either HTTP or HTTPS.

After lots of reading and testing, it came down to this web.config file:

 <system.serviceModel>     <client>       <endpoint binding="customBinding" bindingConfiguration="encryptingBinding" contract="ModuleComm.Commons.ServiceContracts.ModuleService" name="clientConf" />     </client>     <services>       <service name="myServiceWebServer.AsynchronousSocketListener">         <endpoint binding="customBinding" bindingConfiguration="encryptingBinding" contract="ModuleComm.Commons.ServiceContracts.ModuleService" />       </service>       <service behaviorConfiguration="API.Service1Behavior" name="myServiceWebServer.API">         <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" contract="myServiceWebServer.IAPI" />         <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />       </service>     </services>     <behaviors>       <serviceBehaviors>         <behavior name="API.Service1Behavior">           <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />           <serviceDebug includeExceptionDetailInFaults="False" />         </behavior>       </serviceBehaviors>       <endpointBehaviors>         <behavior name="web">           <webHttp />                 </behavior>       </endpointBehaviors>     </behaviors>     <bindings>       <customBinding>         <binding name="encryptingBinding">           <!--  <messageEncryping /> -->           <textMessageEncoding>             <readerQuotas maxStringContentLength="2147483647" />           </textMessageEncoding>           <tcpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">             <connectionPoolSettings leaseTimeout="23:59:00" maxOutboundConnectionsPerEndpoint="10000" />           </tcpTransport>         </binding>       </customBinding>       <webHttpBinding>         <binding name="webBinding">           <security mode="Transport">             <transport clientCredentialType="None"/>           </security>         </binding>       </webHttpBinding>     </bindings>     <protocolMapping>       <add binding="webHttpBinding" bindingConfiguration="webBinding" scheme="https" />     </protocolMapping>   </system.serviceModel> 

When trying to set WebHookURL (e.g: http://localhost:8111) to an http address - code works fine.

Unfortunately, when setting WebHookURL to an https address (e.g: https://localhost:8111) - code won't work and this exception is thrown when trying to create the ServiceHost instance:

Could not find a base address that matches scheme http for the endpoint with binding WebHttpBinding. Registered base address schemes are [https]. 

What am I missing ?

UPDATE 1:

Tried this configurations but i'm getting configuration error: Tried this but i'm getting configuration error:

<system.serviceModel>     <services>             <service behaviorConfiguration="API.Service1Behavior" name="WebServer.API">         <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="webBinding" contract="WebServer.IAPI" />         <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="wsBindingHTTPS" contract="WebServer.IAPI" />         <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />       </service>     </services>     <behaviors>       <serviceBehaviors>         <behavior name="API.Service1Behavior">           <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />           <serviceDebug includeExceptionDetailInFaults="False" />         </behavior>       </serviceBehaviors>       <endpointBehaviors>         <behavior name="web">           <webHttp />                 </behavior>       </endpointBehaviors>     </behaviors>     <bindings>             <wsHttpBinding>                 <binding name="webBinding">           <security mode="None">             <transport clientCredentialType="None"/>           </security>         </binding>         <binding name="wsBindingHTTPS">           <security mode="Transport">             <transport clientCredentialType="None"/>           </security>         </binding>       </wsHttpBinding>     </bindings>   </system.serviceModel> 

4 Answers

Answers 1

the problem is here:

   <webHttpBinding>         <binding name="webBinding">           <security mode="Transport">             <transport clientCredentialType="None"/>           </security>         </binding>       </webHttpBinding> 

The webHttpBinding supports only HTTP requests and not HTTPS requests. webHttpBinding does not support interoperability as well.

WsHttpBinding also supports interoperability. With this binding, the SOAP message is, by default, encrypted. It supports HTTP and HTTPS. In terms of encoding, it provides support for Text as well as MTOM encoding methods. It supports WS-* standards like WS-Addressing, WS-Security and WS-ReliableMessaging. By default, reliable sessions are disabled because it can cause a bit of performance overhead. http://www.codeproject.com/Articles/431291/WCF-Services-Choosing-the-appropriate-WCF-binding

So in order to use https, replace webHttpBinding with WsHttpBinding.

Here is a snippet that will match your solution:

1) Write two endpoints for the service, one is for http and another for https.

<services>     <service behaviorConfiguration="MyServiceBehavior" name="JK.MyService">        <endpoint address="" behaviorConfiguration="WebBehavior" binding="webHttpBinding" bindingConfiguration="webBinding" contract="JK.IMyService">         <identity>           <dns value="localhost" />         </identity>       </endpoint>        <endpoint address="" behaviorConfiguration="WebBehavior" binding="webHttpBinding" bindingConfiguration="webBindingHTTPS" contract="JK.IMyService">         <identity>           <dns value="localhost" />         </identity>       </endpoint>           </service>   </services> 

2) Enable both httpGetEnabled="True" httpsGetEnabled="true" in serviceBehaviors.

<behaviors>  <serviceBehaviors>         <behavior name="MyServiceBehavior">     <serviceMetadata httpGetEnabled="True" httpsGetEnabled="true"/>     <serviceDebug includeExceptionDetailInFaults="true" />   </behavior>       </serviceBehaviors>  <endpointBehaviors>   <behavior name="WebBehavior">     <webHttp/>   </behavior> </endpointBehaviors>  </behaviors> 

3) Write two bindings configurations for http and https. For http give security mode="None" and for https give mode="Transport".

<bindings>     <wsHttpBinding>        <binding name="webBinding">         <security mode="None">           <transport clientCredentialType="None" />         </security>       </binding>        <binding name="webBindingHTTPS">         <security mode="Transport">           <transport clientCredentialType="None" />         </security>       </binding>      </wsHttpBinding>   </bindings> 

Check this link

Answers 2

<services>         <service behaviorConfiguration="API.Service1Behavior" name="WebServer.API">     <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="webBinding" contract="WebServer.IAPI" />     <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="wsBindingHTTPS" contract="WebServer.IAPI" />     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />   </service> </services> 

In the endpoints defined in the configuration above, the value for binding is specified as webHttpBinding. However, the configuration provided for those bindings are defined for wsHttpBinding. Clearly there is a mismatch between the type of binding and its configuration. The below change should fix this error.

<services>         <service behaviorConfiguration="API.Service1Behavior" name="WebServer.API">     <endpoint address="" behaviorConfiguration="web" binding="wsHttpBinding" bindingConfiguration="webBinding" contract="WebServer.IAPI" />     <endpoint address="" behaviorConfiguration="web" binding="wsHttpBinding" bindingConfiguration="wsBindingHTTPS" contract="WebServer.IAPI" />     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />   </service> </services> 

Also in the below snippet, the transport element is redundant since the security mode is None and hence can be removed.

<binding name="webBinding">   <security mode="None">     <transport clientCredentialType="None"/>   </security> </binding> 

Answers 3

Here is another idea: Why not allow HTTPS requests ONLY and re-route http request into https request. If your web server has IIS then you may find this useful

and bar http request can be done like

we generally apply certificate on NLB Node(Network Load Balanced) and configure http to https route on all individual web servers

Answers 4

actually its simple. all you need is one binding for http and another one for https like this:

<bindings>  <basicHttpBinding>     <binding name="SoapBinding"  />  </basicHttpBinding>  <mexHttpBinding>     <binding name="MexBinding" />  </mexHttpBinding>  <mexHttpsBinding>     <binding name="SecureMexBinding" />  </mexHttpsBinding>  <basicHttpsBinding>     <binding name="SecureSoapBinding"  />  </basicHttpsBinding>  <webHttpBinding>     <binding name="RestBinding"  />     <binding name="SecureRestBinding" >      <security mode="Transport" />     </binding>  </webHttpBinding> </bindings>     <services>         <service behaviorConfiguration="ServiceBehavior" name="myServiceWebServer.API">             <endpoint address="soap" binding="basicHttpBinding" bindingConfiguration="SoapBinding" name="Soap" contract="myServiceWebServer.IAPI" />             <endpoint address="soap" binding="basicHttpsBinding" bindingConfiguration="SecureSoapBinding" name="SecureSoap" contract="myServiceWebServer.IAPI" />             <endpoint address="" behaviorConfiguration="Web" binding="webHttpBinding" bindingConfiguration="RestBinding" name="Rest" contract="myServiceWebServer.IAPI" />             <endpoint address="" behaviorConfiguration="Web" binding="webHttpBinding" bindingConfiguration="SecureRestBinding" name="SecureRest" contract="myServiceWebServer.IAPI" />             <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="MexBinding" name="Mex" contract="IMetadataExchange" />             <endpoint address="mex" binding="mexHttpsBinding" bindingConfiguration="SecureMexBinding" name="SecureMex" contract="IMetadataExchange" />         </service>     </services> 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment