none
httpWebRequest connection under selfsigned certificate (IIS) issue RRS feed

  • Question

  • Good afternoon,

       I'm fishing for some help on a httpWebRequest connection under selfsigned certificate (IIS) issue.
       
    Context

       Connecting to a web service (WCF Rest API)
       The site is under ssl (self signed certificate)
       The site is in dev environment.
       The client call the site with httpWebRequest
       
    The problem

        When I call the service in http all work like a charm.
        When I call the service in http I got the following message.

    Error
    -----
        "httpWebRequest The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."

    What I did

        Following some tips found on google I did this:
    ...
    ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
    ...

    What I got

        The type of the error changed for: "The remote server returned an error: (404) Not Found."


    Question

        Is there another way to workaround this?

    Kind regards.
    Claude
    Thursday, November 29, 2018 1:44 PM

Answers

  • I found a solution, 

    I had to configure my web config file as following and now I can request using https with C# code to the WCF Rest service.

    Another problem occurs but not blocking in my case and which is that now the WCF Microsoft client can no longer read the service and produce the error I'll put in the bottom of this note.

    I'd like to thank++ all the person having helped me on this topic.

    Because this service will have to be called from some Web service from Azure I  hope I wont have not any new troubles :)

    Again thank you very much for all the support.

    The web.config that works

    -----------------------------

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <appSettings>
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.5.2">
          <assemblies>
            <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
          </assemblies>
        </compilation>
        <customErrors mode="RemoteOnly" defaultRedirect="mycustompage.htm" />
      </system.web>
      <system.serviceModel>
        <bindings>
          <webHttpBinding>
            <binding name="webHttpTransportSecurity">
              <security mode="Transport" />
            </binding>
          </webHttpBinding>
        </bindings>
        <services>
          <service name="WSMonServ.ServiceMonServ" 
                   behaviorConfiguration="ServiceBehaviour">
            <endpoint address="" 
                      binding="webHttpBinding" 
                      bindingConfiguration="webHttpTransportSecurity" 
                      behaviorConfiguration="jsonEndpointBehavior"        
                      name="json"
                      contract="WSMonServ.IServiceMonServ" />
            
            <endpoint address="mex"
              binding="mexHttpsBinding"
              contract="IMetadataExchange" />
            
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="ServiceBehaviour">
              <serviceMetadata httpGetEnabled="false" />
              <serviceDebug includeExceptionDetailInFaults="false" />
            </behavior>
          </serviceBehaviors>
          <endpointBehaviors>
            <behavior name="jsonEndpointBehavior">
              <webHttp />
            </behavior>
            <behavior name="wsHttpBinding" />
          </endpointBehaviors>
        </behaviors>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
      <system.webServer>
        <directoryBrowse enabled="true" />
        <modules runAllManagedModulesForAllRequests="true" />
      </system.webServer>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <!-- install-package newtonsoft.json -->
            <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>

    The error message  from the WCF Microsoft  client tester

    ---------------------------------------------------------------

    There was no endpoint listening at https://xxx/ServiceComptaPlus.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.

    Server stack trace: 
       at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
       at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
       at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
       at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
       at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

    Exception rethrown at [0]: 
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       at IServiceComptaPlus.GetInfoWebService()
       at ServiceComptaPlusClient.GetInfoWebService()

    Inner Exception:
    The remote server returned an error: (404) Not Found.
       at System.Net.HttpWebRequest.GetResponse()
       at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)





    • Marked as answer by csi-bxl Tuesday, December 4, 2018 12:50 PM
    • Edited by csi-bxl Saturday, December 29, 2018 9:09 AM
    Tuesday, December 4, 2018 12:50 PM

All replies

  • In general SSL should just work with HttpWebRequest. But in SSL both sides have to agree on the protocol. Since everybody has switched to TLS 1.2 you should check to see what the remote endpoint is using and ensure your code is using the same. For newer framework versions it should just work but for older (<= 4.6) you have to adjust your app logic

    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, November 29, 2018 3:15 PM
    Moderator
  • Thank you for the reply,

       In fact both sides (client/WCF rest) are using .Net 4.5.2 therefore I suppose this should be the problem, am I wrong?

       And this issue occurend on the same machine, one console code  talking to code in IIS on the same pc.

    Thursday, November 29, 2018 3:40 PM
  • .NET 4.5.2 doesn't support TLS 1.2 out of the box. You'd have to follow the steps to enable it.

    Are you sure the cert is good? Can you use the WCF Test Client and connect to that endpoint and call methods when using HTTPS? If it doesn't work then your app won't.

    Also, I should point out that you generally won't use HttpWebRequest with WCF. WCF is very picky about the SOAP envelope. If anything is wrong it'll fail the call. So if WCF Test Client works then I'd say the next step is to use a service reference to call the endpoint with HTTPS. If that works then the WCF side is fine and the problem is on the client side.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, November 29, 2018 4:25 PM
    Moderator
  • Thank you Michael,

    Seems there is a lot of things to to take into account here!

    You ask if my certificate is good, but it is a self signed one (IIS).

    Therefore trying to make a connection to my WCF Rest web serv using this selfcert is wasted effort or it is connectable anyway and it is stil a TLS issue?

    Another question about framework version, <= 4.6 means at least 4.7 or 4.6.2 is ok?

    Kind regards.

    Claude


    • Edited by csi-bxl Friday, November 30, 2018 9:02 AM
    Friday, November 30, 2018 8:59 AM
  • "You ask if my certificate is good, but it is a self signed one (IIS). "

    Right but cert have to be configured for client auth, server auth, etc. If you generated it from IIS directly then it should be fine. If you created it yourself that is a different story. 

    " and it is stil a TLS issue"

    Did you do the quick test using WCF Test Client to https? If that works then the cert is valid and it is likely an issue on the client side.

    Given the error my gut instinct is a protocol version mismatch. This is the error you'd get and it is the most common one. There are other causes but protocol version is the most common.

    "<= 4.6 means at least 4.7 or 4.6.2 is ok?"

    Yes. The document I linked to discusses what you need to do to configure/turn on TLS 1.2 in your web service AND client code. They must both agree to the protocol(s) to use and everybody has switched to TLS 1.2. But older (e.g. < 4.7.1) versions of the framework either don't support or have to opt into this support. Knowing which TLS version you're using would help and that is where connecting using the browser would help as the browsers generally show you TLS version information.

    For 4.5.2 it doesn't support TLS 1.2 so you'd have to turn it on. More recent OSes and upgrades are disabling the older protocols as they are not secure. So if you aren't using TLS 1.2 you're going to have an issue connecting (like you are now).


    Michael Taylor http://www.michaeltaylorp3.net

    Friday, November 30, 2018 3:28 PM
    Moderator
  •   Thank you for the support and advices. 'm still fighting with this issue.
      
      Now I have I certified Certificate.
      
      0] Test I did
      -------------   
      I installed it in iis and I can access now with browsers (Chrome/IE) without any warning issues. (" So happy! ")
      
      1] Test I did
      -------------
      I tried the client exe WCF against the service but no methods are showned nor any error message, just a blank windows.
      
      2] Test I did
      -------------   
      I ran the client C# code against the WCF service (in http: port 51175) using the new domain name associated with the certificate.
      -> all is running fine, no errors and answers expected are returned.
      
      3] Test I did
      -------------  
      I ran the C# code against the WCF service (in https: port 51171) using the new domain name associated with the certificate.
      -> I received "The remote server returned an error: (404) Not Found." (I remind that with browser the service was found, cf  point 0]) 
      
      4] Test I did
      -------------     
      I ran the client C# code against the WCF service (in https: port 51171)) using the new domain name associated with the certificate,
      calling either from the client and the server the 2 following methods
      
      Server
      -----------------------------------------
      
        protected void Application_Start(object sender, EventArgs e)
            {
                System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
                ServicePointManager.ServerCertificateValidationCallback += (se, certificate, chain, sslPolicyErrors) => true;
            }

      Client 
      -----------------------------------------
      
            System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
                ServicePointManager.ServerCertificateValidationCallback += (se, certificate, chain, sslPolicyErrors) => true;
    ...
    the code call
       
      -> I received "The remote server returned an error: (404) Not Found." 
      
      5] Test I did
      -------------     
      I ran the client C# code against the WCF service (in https: port 51171)) using the new domain name associated with the certificate,
      WITHOUT calling either from the client and the server the 2 following methods in point  4]
      
      I'm still quite very open to any suggestions.
      
      Kind regards.
      Claude
    • Edited by csi-bxl Monday, December 3, 2018 4:11 PM
    Monday, December 3, 2018 4:10 PM
  • When you start talking about ports and IIS then this really becomes a web server question. But to see if that matters I have some questions.

    1) Not sure what you mean here. The WCF Test Client? If you pointed to the URL then you should have seen a list of WCF endpoints. If you didn't get any then none of your services are exposing MEX and that is an issue.

    3) To use SSL you have to configure SSL on your site and you have to set up a binding. Normally you don't configure a port. HTTP is 80 and HTTPS is 443. You would only change these if you were already hosting sites on those ports. In general the default web site is going to use those ports so don't change those. Note that if you're using IISX then it will auto-generate the first port and the SSL port as well. The SSL port in this case however has to be in the 65000 range otherwise IISX won't allow it. 404 indicates to me you aren't using the correct port. Again, for IIS, the default configured ports shouldn't be changed. But you do need to configure SSL for the WCF service application (in IIS) in addition to configured it at the site level.

    4) 


    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, December 4, 2018 3:30 AM
    Moderator
  • Hello Michael,

       I followed your advices (described in below points "What I did" ) and things  evolved :).

       Now coool! I have something displayed in the WCF Microsoft client and I'm able to ask displayed methods of my service using the https link



       Having now this WCF Microsoft client working I tried my C# client code against the web service (https) and I encounter a new type of error:

    My code calling and receiving:

    System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
    var httpWebRequest = (HttpWebRequest)WebRequest.Create(_clientConfiguration.UriString + "\\" + attribute.Url);
    httpWebRequest.ContentType = "application/json; charset=utf-8; ";
    httpWebRequest.Method = "POST";
    var json = JsonHelp.JsonSerialize(dRequest);
    using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())) { streamWriter.Write(json); }
    var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();

    Error response: 

    "The remote server returned an error: (415) Cannot process the message because the content type 'application/json; charset=utf-8;' was not the expected type 'text/xml; charset=utf-8'.."

       After some search on googled I found suggestion to change in the web.config "basicHttpBinding" to "webHttpBinding". When I did this 

       The error was "The remote server returned an error: (500) Internal Server Error."

       and with the WCF Microsoft client tool the error now was

    "The content type application/xml; charset=utf-8 of the response message does not match the content type of the binding (text/xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 710 bytes of the response were: '<Fault xmlns="http://schemas.microsoft.com/ws/2005/05/envelope/none"><Code><Value>Sender</Value><Subcode><Value xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:ActionNotSupported</Value></Subcode></Code><Reason><Text xml:lang="fr-BE">The message with Action '' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver.  Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).</Text></Reason></Fault>'.

    Server stack trace: 
       at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory`1 factory, WebException responseException, ChannelBinding channelBinding)
       at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
       at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
       at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
       at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

    Exception rethrown at [0]: 
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       at IServiceComptaPlus.GetInfoWebService()
       at ServiceComptaPlusClient.GetInfoWebService()

    Inner Exception:
    The remote server returned an error: (500) Internal Server Error.
       at System.Net.HttpWebRequest.GetResponse()
       at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)"


    What I did
    ------------

    For the point 1]

    I was talking about "WCF Test Client" a microsoft tool to test WCF services. When I try to use it against the service (http or https) I get a blank page withot error messages.
    If I use a browser a find the svc page with wsl and services exposed.


    For the point 3]

    Multiple sites will have a https access therefore I use different ports for that purpose.
    I made the bindings to the certificate.

    I followed your advice and found more info on how to configure iis more deeper an I did the following supplementary stuffs:

    IIS

    - SSL Require SSL -> click on 'Apply'
    - Client certificate: ignore
    - -> click on 'Apply'

    web.configurations

    - added

    <bindings>  
          <basicHttpBinding>  
            <binding name="secureHttpBinding">  
              <security mode="Transport">  
                <transport clientCredentialType="None"/>  
              </security>  
            </binding>  
          </basicHttpBinding>  
    </bindings>  

    ...


    <endpoint address="mex"  
      binding="mexHttpsBinding"  
      contract="IMetadataExchange" />



                                                         
    • Edited by csi-bxl Tuesday, December 4, 2018 11:06 AM
    Tuesday, December 4, 2018 10:32 AM
  • I found a solution, 

    I had to configure my web config file as following and now I can request using https with C# code to the WCF Rest service.

    Another problem occurs but not blocking in my case and which is that now the WCF Microsoft client can no longer read the service and produce the error I'll put in the bottom of this note.

    I'd like to thank++ all the person having helped me on this topic.

    Because this service will have to be called from some Web service from Azure I  hope I wont have not any new troubles :)

    Again thank you very much for all the support.

    The web.config that works

    -----------------------------

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <appSettings>
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.5.2">
          <assemblies>
            <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
          </assemblies>
        </compilation>
        <customErrors mode="RemoteOnly" defaultRedirect="mycustompage.htm" />
      </system.web>
      <system.serviceModel>
        <bindings>
          <webHttpBinding>
            <binding name="webHttpTransportSecurity">
              <security mode="Transport" />
            </binding>
          </webHttpBinding>
        </bindings>
        <services>
          <service name="WSMonServ.ServiceMonServ" 
                   behaviorConfiguration="ServiceBehaviour">
            <endpoint address="" 
                      binding="webHttpBinding" 
                      bindingConfiguration="webHttpTransportSecurity" 
                      behaviorConfiguration="jsonEndpointBehavior"        
                      name="json"
                      contract="WSMonServ.IServiceMonServ" />
            
            <endpoint address="mex"
              binding="mexHttpsBinding"
              contract="IMetadataExchange" />
            
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="ServiceBehaviour">
              <serviceMetadata httpGetEnabled="false" />
              <serviceDebug includeExceptionDetailInFaults="false" />
            </behavior>
          </serviceBehaviors>
          <endpointBehaviors>
            <behavior name="jsonEndpointBehavior">
              <webHttp />
            </behavior>
            <behavior name="wsHttpBinding" />
          </endpointBehaviors>
        </behaviors>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
      <system.webServer>
        <directoryBrowse enabled="true" />
        <modules runAllManagedModulesForAllRequests="true" />
      </system.webServer>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <!-- install-package newtonsoft.json -->
            <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>

    The error message  from the WCF Microsoft  client tester

    ---------------------------------------------------------------

    There was no endpoint listening at https://xxx/ServiceComptaPlus.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.

    Server stack trace: 
       at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
       at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
       at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
       at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
       at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

    Exception rethrown at [0]: 
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       at IServiceComptaPlus.GetInfoWebService()
       at ServiceComptaPlusClient.GetInfoWebService()

    Inner Exception:
    The remote server returned an error: (404) Not Found.
       at System.Net.HttpWebRequest.GetResponse()
       at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)





    • Marked as answer by csi-bxl Tuesday, December 4, 2018 12:50 PM
    • Edited by csi-bxl Saturday, December 29, 2018 9:09 AM
    Tuesday, December 4, 2018 12:50 PM
  • In your serviceMetadata element you didn't turn on HTTPS so it won't allow you to access the metadata vs HTTPS. Also note that you should strongly consider blocking HTTP altogether for your service. To do that you can set SSL settings in IIS to require SSL. Then the HTTP endpoint won't be supported at all.

    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, December 4, 2018 6:20 PM
    Moderator
  • Hello Michael,

    According with what you said, I added then in the config

    And in IIS I got this

    Was these what you mean?

    Best regards.

    Claude

    Friday, December 7, 2018 10:19 AM
  • Oups, therefore did no longer work, I change the config to  

    then it works, but still when calling with WCF client, nothing showed 

    Claude

    Friday, December 7, 2018 10:25 AM
  • I see in the status bar is says you added the service successfully but I don't see anything in the editor. Something isn't right. At a minimum you should see the URL of your service. You are using the (HTTPS) URL to your *.svc file right? If you take that URL and browse to it in the browser do you get the WCF help page?

    I'm sorry, I'm going back and re-reading your initial set of posts to see what the original problem was and some things are standing out that I didn't notice earlier. Firstly, WCF does not do or support REST. If you're using WCF then you're writing a SOAP service, not REST. So to clarify you have a .svc file in your project that points to a class in the backend that implements an interface. The interface has a ServiceContract attribute on it and each method has an OperationContract right?

    The binding you're using is not the standard binding we would use for WCF. It should work but I do wonder if it is correct. Here's an example of what a typical WCF service model configuration might look like.

    <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <!-- Default behavior for services -->
            <behavior>
              <serviceMetadata httpsGetEnabled="true" />
              <serviceDebug IncludeExceptionDetailInFaults="true" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
        <!-- Only supporting HTTPS here - to support HTTP as well add another mapping to the HTTP binding and scheme http -->
        <protocolMapping>
          <add binding="apiHttpsBinding" scheme="https"/>
        </protocolMapping>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
    
          <!-- If you want to support both HTTP and HTTPS you need to ensure multipleSiteBindingsEnabled is true otherwise remove it so only 1 binding works -->
          <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    
        <bindings>
           <!-- WS HTTP binding is good for public facing services but Basic HTTP binding is better for internal services, if unsure start with Basic -->
             <wsHttpBinding>
                <!-- To support HTTP as well you need to add another binding with security set to None -->
                <binding name="apiHttpsBinding" 
                   <security mode="Transport">
                      <transport clientCredentialType="None" />
                   </security>
                </binding>
             </wsHttpBinding>
          </bindings>
    
        <services>
          <service name="MyService">
            <endpoint address="" binding="wsHttpBinding" bindingConfiguration="apiHttpsBinding" contract="IMyInterface" />
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
          </service>
        </services>
      </system.serviceModel>


    Michael Taylor http://www.michaeltaylorp3.net

    Friday, December 7, 2018 4:12 PM
    Moderator
  • Hello Michael,

       Thank you for the web.config.

       Before modifying myt web config I'd like to add inside the existent (and working) one the possibility to connect not only with https (which is working) but still with HTTP because I need to test new features on my local environmement which is in http.

       How can I achiev this? I tried different things but nothing seems to be working.

       In my local iis I configured

        

    And my web.config is

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      
      <system.web>
        <compilation debug="true" targetFramework="4.5.2">
          <assemblies>
            <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
          </assemblies>
        </compilation>
        <customErrors mode="RemoteOnly" defaultRedirect="mycustompage.htm" />
      </system.web>
      <system.serviceModel>
        <bindings>
          <webHttpBinding>
            <binding name="webHttpTransportSecurity">
              <security mode="Transport" />
            </binding>
          </webHttpBinding>
        </bindings>
        <services>
          <service name="WSComptaPlus.ServiceComptaPlus" behaviorConfiguration="ServiceBehaviour">
            <endpoint address="" 
                      binding="webHttpBinding" 
                      bindingConfiguration="webHttpTransportSecurity" 
                      behaviorConfiguration="jsonEndpointBehavior" 
                      name="json" 
                      contract="WSComptaPlus.IServiceComptaPlus" />

            <endpoint 
    address="mex" 
    binding="mexHttpsBinding" 
    contract="IMetadataExchange" />
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="ServiceBehaviour">
              <serviceMetadata httpsGetEnabled="true" />
              <serviceDebug includeExceptionDetailInFaults="false" />
            </behavior>
          </serviceBehaviors>
          <endpointBehaviors>
            <behavior name="jsonEndpointBehavior">
              <webHttp />
            </behavior>
            <behavior name="wsHttpBinding" />
          </endpointBehaviors>
        </behaviors>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
      <system.webServer>
        <directoryBrowse enabled="true" />
        <modules runAllManagedModulesForAllRequests="true" />
      </system.webServer>
    </configuration>

    When I connect with https I got the expected answer from the service

    https://localhost/ServiceComptaPlus.svc/info/ws

    When I connect with http like http://192.168.1.2:81/ServiceComptaPlus.svc

    I got the correct description ...

    But when I call http://192.168.1.2:81/ServiceComptaPlus.svc/info/ws, I got one error

    Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly. 

    I suppose this is a web.config issue.

    Can you help me on this point?

    Kinf regards.
    Claude

    Tuesday, December 25, 2018 4:08 PM
  • "but still with HTTP because I need to test new features on my local environmement which is in http."

    No, that is fundamentally wrong. You should always test your code in the same setup as your production setup. If you don't then you have no way of knowing whether you broke something until it gets to Prod. This completely defeats the purpose of testing.

    Locally you should only be using HTTPS if that is what your service requires. IISX supports that out of the box. All you need to do is go to the properties window (not the project properties) and set the option to use HTTPS. Then in the project properties tab ensure the new HTTPS address (and port) is configured as the startup URL. Then run your service and it'll be running under HTTPS. You can now test like you would in prod. There is no reason to configure HTTP.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, December 26, 2018 4:03 PM
    Moderator
  • Hello Michael,

       Indeed it's better to keep all in https in this case, but I encountered refusal to do so because locally a fake certificate makes the client (code c#)  connection fail, but I'll then try to follow your configuration advices to see if my client still can connect with the service.

    Could you be more specific about the way I have to configure the "windows", the one in visual studio? If so I cannot see any https config stuff? In IIS?

       The context is I have a wcf web service called by c# client code. Have I to configure the client side too?

       By the way could you still indicate me how to configure the web.config to allow http too?

    Kind regaerds.

    Claude




    • Edited by csi-bxl Friday, December 28, 2018 12:51 PM
    Friday, December 28, 2018 12:36 PM
  • The Properties window is accessible from the View menu. Alternatively F4 (on the standard profile) will also bring it up. It'll pop up as a tool window. Then select your web project in Solution Explorer. you'll have options around enabling SSL. Set that option and a new HTTPS URL will be generated. Copy that URL and then go to the project's properties (right click the project in Solution Explorer and select Properties). Go to the Web tab and ensure the HTTPS URL is the startup URL.


    Michael Taylor http://www.michaeltaylorp3.net

    Friday, December 28, 2018 2:54 PM
    Moderator
  • Hello Michael,

       When I select 'View->Properties windows' on VS nothing happen, either if I press F4.

       Mean while because I'm blocked in my developpments with this issue (because while in hollidays I cannot access the remote IIS working with https) I really need to be able to modify my current 'web.config' to  make it possible to work in http and https in the same time.

       I'll then start a fresh forum question whith only this simple issue. 

       I you can help me just on this I'd be only too happy.

    Kind regards.

    Claude



    • Edited by csi-bxl Saturday, December 29, 2018 9:23 AM
    Saturday, December 29, 2018 9:22 AM
  • "View->Properties windows' on VS nothing happen, either if I press F4"

    Chances are the window is already open in your editor then. It is a tool window so it'll appear alongside things like Solution Explorer, Team Explorer, etc. 

    "I really need to be able to modify my current 'web.config' to  make it possible to work in http and https in the same time."

    To make the server work with HTTP or HTTPS you have to make a couple of changes. Going back to the early serviceModel section I posted you will see some comments about enabling HTTP as well.

    Your config is a lot more complicated than a standard WCF service. I notice this is a 4.5.2 version so that would explain a lot since the configs used to be very verbose but now are pretty simple because they default a lot. As an example here's the config generated for a new WCF service and it supports either HTTP or HTTPS via BasicHttpBinding out of the box, including MEX.

    <?xml version="1.0"?>
    <configuration>
    
      <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.6.1" />
        <httpRuntime targetFramework="4.6.1"/>
      </system.web>
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior>
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
              <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <protocolMapping>
            <add binding="basicHttpsBinding" scheme="https" />
        </protocolMapping>    
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
      <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
      </system.webServer>
    </configuration>

    It just works. In a perfect world you should start with the simple config and then expand to include the binding and configurations you need special (like your JSON stuff). Here's one that more closely matches your current config.

    <?xml version="1.0"?>
    <configuration>
    
        <appSettings>
            <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
        </appSettings>
        <system.web>
            <compilation debug="true" targetFramework="4.6.1" />
            <httpRuntime targetFramework="4.6.1"/>
        </system.web>
        <system.serviceModel>
            <services>
                <!-- Need 2 endpoints, one for HTTP and another for HTTPS -->
                <service name="Service1">
                    <endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttp" behaviorConfiguration="webBehavior"
                              contract="Service1.IService1" />
                    <endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttps" behaviorConfiguration="webBehavior"
                              contract="Service1.IService1" />
                </service>
            </services>
    
            <behaviors>
                <serviceBehaviors>
                    <!-- Unnamed behaviors are applied to all bindings -->
                    <behavior>
                        <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                        <serviceDebug includeExceptionDetailInFaults="false"/>
                    </behavior>                                
                </serviceBehaviors>
                
                <!-- Specific to endpoints -->
                <endpointBehaviors>                
                    <behavior name="webBehavior">
                        <webHttp />
                    </behavior>
                </endpointBehaviors>
            </behaviors>
    
            <!-- Using webHttpBinding so have to configure by hand, one for each HTTP and HTTPS -->
            <bindings>
                <webHttpBinding>
                    <!-- HTTPS -->
                    <binding name="webHttps">
                        <security mode="Transport">
                            <transport clientCredentialType="None" />
                        </security>
                    </binding>
                    
                    <!-- HTTP -->
                    <binding name="webHttp">
                        <security mode="None" />
                    </binding>
                </webHttpBinding>
            </bindings>
            
            <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
        </system.serviceModel>
        <system.webServer>
            <modules runAllManagedModulesForAllRequests="true"/>
        </system.webServer>
    </configuration>

    The problem you're going to run into is that you're using webHttpBinding. That means it is using HTTP methods and not SOAP. That will conflict with MEX which uses HTTP to discover the service and generate the proxy (either for a client or even for the WCF test client). You cannot mix the two. This is a known issue with webHttp and one of the reasons that WCF shouldn't be used for REST APIs. If you need REST then use Web API instead. If you connect to the service using WcfTestClient you'll notice it is using the BasicHttpBinding. That is what it'll use so you'll have to test your service with custom code instead and note that service discovery in VS doesn't work with webHttpBinding either AFAIK.

    I think this thread has gone in an entirely different direction than where it started. The original question was related to getting HttpWebRequest working with SSL (a client side issue). We're now in IIS/WCF land (ASP.NET) and talking about webHttpBinding (which doesn't work with MEX). I think the original question is answered and that further questions about configuring WCF and webHttpBinding should be posted in the WCF forums.


    Michael Taylor http://www.michaeltaylorp3.net

    Saturday, December 29, 2018 5:51 PM
    Moderator