WCF over SSL - 404 error
Asked Answered
T

10

43

Okay, I must be missing something utterly simple here, because I've been googling for days, and looking at dozens of answers there, and here on SO, and i just CANNOT get this to work, no matter what i've tried. The service works perfectly fine when called over plain HTTP.

Here's our setup... we have a domain, http://www.mydomain.com . We have an SSL certificate installed on that domain from thawte, just as we would if we were securing an e-commerce site. That all works fine, and i can go to https://www.mydomain.com and it works right. I'm running VS2008, .NET 3.5 site on Windows Server 2003 R2.

Now, I added a Silverlight-enabled WCF service to my site, which i want to communicate with over SSL. If i browse to https://www.mydomain.com/myservice.svc, it shows me the WSDL-descriptive "You have created a service" page as expected, which shows to create your client using

svcutil.exe https:// ... 

EDIT: I realized the url shown for the svcutil in the wsdl file was actually pointing to the physical box name of the web server, not the proper domain. So i went through the steps shown in this blog posting to update the SecureBinding of the website in IIS using the adsutil script. Now the wsdl file shows the correct SSL address, but i still get the same error.

Now i went and tried to hook my Silverlight app up to it, and it does not work, returning an exception in the result from the async calls, stating "The remote server returned an error: NotFound. A number of the blogs i've read talked about narrowing it down to Silverlight issues by creating a test Windows application, and trying to reference it from that. Well, I did that and even in a regular windows application trying to access the service over SSL i get an exception stating:

System.ServiceModel.EndpointNotFoundException: 
There was no endpoint listening at https://www.mydomain.com/mysubdir/myservice.svc that could accept the message. 
This is often caused by an incorrect address or SOAP action. 
See InnerException, if present, for more details. ---> 
System.Net.WebException: The remote server returned an error: (404) Not Found.
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

This despite the fact that i explicitly added the service reference to the Windows app using the HTTPS scheme and it properly gets all the methods and shows them in Intellisense in the editor.

Note that this is a service which does NOT require explicit log in on the user's part. I am going to be sending custom headers in my SOAP envelopes to verify that the requests are coming from our app, and I just want to keep predators from sniffing the line and picking out the custom headers.

Now to the code, where i must just have some stupid little setting wrong, because from all i've read, this should be a fairly straightforward exercise.

First, my service's code-behind class is decorated with the following attributes:

<ServiceBehavior(AddressFilterMode:=AddressFilterMode.Any)> 
<AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Allowed)>

The ServiceModel section of my web.config on the server looks like so:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="basicHttpBinding">
                <security mode="Transport">
                    <transport clientCredentialType ="None"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="standingsBehavior">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
                    <serviceDebug includeExceptionDetailInFaults="false"/>
                </behavior>
            </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
        <baseAddressPrefixFilters>
            <add prefix="http://www.mydomain.com:80"/>
        </baseAddressPrefixFilters>
    </serviceHostingEnvironment>
    <services>
        <service behaviorConfiguration="standingsBehavior" name="lijslwebdata">
            <endpoint address="" binding="basicHttpBinding" contract="lijslwebdata"/>
            <!--<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>-->
        </service>
    </services>
</system.serviceModel>

And the ServiceModel section of the app.config in my Windows application looks like the following:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_lijslwebdata" closeTimeout="00:01:00"
                openTimeout="00:01:00" receiveTimeout="00:10:00" 
                sendTimeout="00:01:00" allowCookies="false" 
                bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                maxBufferSize="65536" maxBufferPoolSize="524288" 
                maxReceivedMessageSize="65536" messageEncoding="Text" 
                textEncoding="utf-8" transferMode="Buffered"
                useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192"
                    maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <security mode="Transport">
                    <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
                    <message clientCredentialType="UserName" algorithmSuite="Default" />
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="https://www.mydomain.com/mysubdir/myservice.svc"
            binding="basicHttpBinding" 
            bindingConfiguration="BasicHttpBinding_lijslwebdata"
            contract="xdata.lijslwebdata" name="BasicHttpBinding_lijslwebdata" />
    </client>
</system.serviceModel>
Triumvirate answered 5/10, 2009 at 16:37 Comment(2)
One question, does the baseAddressPrefixFilters need to be set to HTTPS in some fashion??Triumvirate
I'd really be interested in this, too. I have an HTTP WCF service at the moment and expect trouble when providing option of HTTPS. Please remember to post your result! :)Youngs
T
1

Okay, I apparently fixed the issue, and I have absolutely no idea why/how.

Here's what I did.

  • I added a BRAND NEW EMPTY Silverlight-enabled WCF service
  • I then updated the web.config to reflect both services
  • I then literally just copied and pasted everything about the first service into the second service, except the name.

Why this fixed it, I have absolutely NO idea.

FWIW for anyone, here is my new web.config ServiceModel section with the second service in it...

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="basicHttpBinding">
            </binding>
            <binding name="basicHttpsBinding">
                <security mode="Transport">
                    <transport clientCredentialType ="None"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="standingsBehavior">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
        <baseAddressPrefixFilters>
            <add prefix="http://www.mydomain.com/"/>
        </baseAddressPrefixFilters>
    </serviceHostingEnvironment>
    <services>
        <service behaviorConfiguration="standingsBehavior" name="lijslwebdata">
            <endpoint address="" binding="basicHttpBinding" contract="lijslwebdata"/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
        <service behaviorConfiguration="standingsBehavior" name="sslwebdata">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpsBinding" contract="sslwebdata"/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
    </services>
</system.serviceModel>
Triumvirate answered 6/10, 2009 at 18:28 Comment(2)
... and that fills me with the same dread as the rest of WCF/Silverlight does. Too many variables. Create a new project from scratch and it will "just work". Not an option in the real world! (I've had to do it before). Thanks for your answer.Youngs
I agree, ... though my problem was not so much with Silverlight, because even my test Windows client couldn't connect originally. It was something strictly with the WCF over SSL part of it. But I agree... I don't like things that just automagically fix themselves. It is a nice technology and all, just needs to be a little less fragile.Triumvirate
A
30

I had this same issue on my end. Your post helped me figure out what the issue was. here is my service model section. I discovered that the keys were the httpsGetEnabled then setting the bindingconfiguration I hope this helps.

<system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="RequestImageBehavior">
                    <serviceMetadata **httpsGetEnabled**="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                  <dataContractSerializer maxItemsInObjectGraph="1073741824" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <services>
            <service behaviorConfiguration="RequestImageBehavior" name="RequestImage">
                <endpoint address="" 
                          binding="wsHttpBinding" 
                          **bindingConfiguration**="HttpsBinding"
                          contract="IRequestImage">
                </endpoint>
                <endpoint address="mex" 
                          binding="mexHttpBinding" 
                          contract="IMetadataExchange" />
            </service>
        </services>
      <bindings>
        **<wsHttpBinding>
          <binding name="HttpsBinding">
            <security mode="Transport">
              <transport clientCredentialType="None"/>
            </security>
          </binding>
        </wsHttpBinding>**
      </bindings>
    </system.serviceModel>
Adelia answered 12/11, 2009 at 19:31 Comment(3)
I had the same resolution. I found that my bindingConfiguration wasn't set but my bindingName was. Once I set the binding configuration things started working as they should. Thanks!Tryout
This fixed it for me, BUT I had to rename <wsHttpBinding> to <webHttpBinding - perhaps a difference in .NET versions?Wolfhound
theyetiman, check-out this link for the difference between wsHttpBinding and webHttpBinding. Totally different ballgame. #2651285Contribute
F
14

I was dealing with this recently, and want to add a tweak. If you follow the above instructions, you'll be able to get the service to work with HTTPS, but not simultaneously work on both HTTP and HTTPS. To do that, you need to have two endpoint configuration nodes, one for each protocol as follows:

 <service name="MyCompany.MyService" >
    <endpoint address="" behaviorConfiguration="AspNetAjaxBehavior"
      binding="webHttpBinding" contract="MyCompany.MyService" bindingConfiguration="sslBinding" />
    <endpoint address="" behaviorConfiguration="AspNetAjaxBehavior"
      binding="webHttpBinding" contract="MyCompany.MyService" />
  </service>

(taken from my codebase, adjust behaviorConfiguration and binding as appropriate)

Faddish answered 7/7, 2010 at 18:21 Comment(1)
Thank you!! I actually found that my SSL service over HTTPS returned a 404 without the HTTP endpoint. Adding the HTTP endpoint fixed it. Ridiculous.Yclept
H
8

I just spent a few hours on this and it turned out my problem was the service name

<services>
      <service name="TimberMill.Web.Data.LogReceiverService">
        <endpoint binding="basicHttpBinding" bindingConfiguration="basicBinding"
                     contract="NLog.LogReceiverService.ILogReceiverServer" />
      </service>
    </services>

had to exactly match the similar entry in my *.svc file.

<%@ ServiceHost 
    Language="C#" 
    Debug="true" 
    Service="TimberMill.Web.Data.LogReceiverService, TimberMill.Web"
    Factory="Autofac.Integration.Wcf.AutofacServiceHostFactory, Autofac.Integration.Wcf"
    CodeBehind="LogReceiverService.svc.cs" 
%>

I'm not sure if it was related to my use of Autofac. It all was working fine under plain HTTP. Failed under HTTPS though.

Well I think so, I don't want to disturb anything now by testing in more detail lest I anger the WCF-Config gods and my config breaks again. YMMV.

Hogshead answered 10/10, 2012 at 5:35 Comment(1)
Yes serviceName fixed this for meGalateah
Q
5

In my case non of these answers helped.

Instead, I needed to add a duplicate <binding> section that has no name attribute set.

Here is the dump of the appropriate section of my service's web.config file:

<behaviors>
    <serviceBehaviors>
        <behavior name="ServiceBehaviour">
            <serviceMetadata 
                httpsGetEnabled="true" 
                httpsGetUrl="RemoteSyncService.svc"
                httpGetBindingConfiguration="bindingConfig" />
            <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
        <behavior name="">
            <serviceMetadata 
                httpsGetEnabled="true" 
                httpsGetUrl="RemoteSyncService.svc" />
            <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
    </serviceBehaviors>
</behaviors>

<bindings>
  <basicHttpBinding>
    <binding name="bindingConfig" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" transferMode="Streamed">
        <security mode="Transport">
          <transport clientCredentialType="None"/>
        </security>
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
    </binding>

    <!-- Add binding with EMPTY/MISSING name, see https://forums.iis.net/t/1178173.aspx -->
    <binding maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" transferMode="Streamed">
        <security mode="Transport">
          <transport clientCredentialType="None"/>
        </security>
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
    </binding>
  </basicHttpBinding>
</bindings>

I do hope this might be helpful for someone, some day.

Quickwitted answered 8/11, 2015 at 18:52 Comment(1)
Just to validate this post, this was the only suggestion that worked for meFineberg
N
3

I had the same issue and spent one day to resolve this issue. Finally below configuration worked me for HTTPS access.

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="basicHttpBinding">
            </binding>
            <binding name="basicHttpsBinding">
                <security mode="Transport">
                    <transport clientCredentialType ="None"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="standingsBehavior">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
        <baseAddressPrefixFilters>
            <add prefix="http://www.mydomain.com/"/>
        </baseAddressPrefixFilters>
    </serviceHostingEnvironment>
    <services>
        <service behaviorConfiguration="standingsBehavior" name="lijslwebdata">
            <endpoint address="" binding="basicHttpBinding" contract="lijslwebdata"/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
        <service behaviorConfiguration="standingsBehavior" name="sslwebdata">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpsBinding" contract="sslwebdata"/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
    </services>
</system.serviceModel>
Nobleminded answered 8/9, 2011 at 20:36 Comment(0)
V
1

Everything seems to be quite valid, no glaring mistakes at all...

Just one observation/question: where is your *.svc file located??

In the error message, I see:

 https://www.mydomain.com/myservice.svc 

Is your *.svc file really in the top-level virtual directory of your site?

Typically, the *.svc file is inside a virtual directory on IIS and thus the address would be something like:

 https://www.mydomain.com/YourVirtualDirectory/myservice.svc 

Of course, you can deploy an ASP.NET app and a WCF service *.svc file to the root of your IIS - but it's not very common, in my experience.

Just a thingie to check.....

Marc

Vacuva answered 5/10, 2009 at 19:4 Comment(1)
Yes, no, the service is actually in a sub-directory. I just renamed the paths for security purposed. Guess i should've put in a subdir in the fake path, but no, it's in a subdir.Triumvirate
T
1

Okay, I apparently fixed the issue, and I have absolutely no idea why/how.

Here's what I did.

  • I added a BRAND NEW EMPTY Silverlight-enabled WCF service
  • I then updated the web.config to reflect both services
  • I then literally just copied and pasted everything about the first service into the second service, except the name.

Why this fixed it, I have absolutely NO idea.

FWIW for anyone, here is my new web.config ServiceModel section with the second service in it...

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="basicHttpBinding">
            </binding>
            <binding name="basicHttpsBinding">
                <security mode="Transport">
                    <transport clientCredentialType ="None"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="standingsBehavior">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
        <baseAddressPrefixFilters>
            <add prefix="http://www.mydomain.com/"/>
        </baseAddressPrefixFilters>
    </serviceHostingEnvironment>
    <services>
        <service behaviorConfiguration="standingsBehavior" name="lijslwebdata">
            <endpoint address="" binding="basicHttpBinding" contract="lijslwebdata"/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
        <service behaviorConfiguration="standingsBehavior" name="sslwebdata">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpsBinding" contract="sslwebdata"/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
    </services>
</system.serviceModel>
Triumvirate answered 6/10, 2009 at 18:28 Comment(2)
... and that fills me with the same dread as the rest of WCF/Silverlight does. Too many variables. Create a new project from scratch and it will "just work". Not an option in the real world! (I've had to do it before). Thanks for your answer.Youngs
I agree, ... though my problem was not so much with Silverlight, because even my test Windows client couldn't connect originally. It was something strictly with the WCF over SSL part of it. But I agree... I don't like things that just automagically fix themselves. It is a nice technology and all, just needs to be a little less fragile.Triumvirate
N
1

It didn't work for you before because you named your basicHttpBinding configuration basicHttpBinding but did not reference that configuration in your <service> tag with the bindingConfiguration="basicHttpBinding"

In your changes that did work by adding another service configuration you then did reference the binding configuration that contains the <security> node hence causing it work.

Nullifidian answered 15/7, 2011 at 3:33 Comment(0)
U
1

Several of the answers led me into reconfigure my web.config to contain two endpoints. I ended up with this following Web.config.

<system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="basicHttpBinding">
        </binding>
        <binding name="basicHttpsBinding">
          <security mode="Transport">
            <transport clientCredentialType ="None"/>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="standingsBehavior">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
      <baseAddressPrefixFilters>
        <add prefix="http://www.myhost.com"/>
      </baseAddressPrefixFilters>
    </serviceHostingEnvironment>

    <services>
      <service behaviorConfiguration="standingsBehavior" name="NameSpace.ClassName">
        <endpoint address="" binding="basicHttpBinding" contract="NameSpace.ContractInterfaceName"/>
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpsBinding" contract="NameSpace.ContractInterfaceName"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
  </system.serviceModel>
Upanishad answered 7/5, 2018 at 8:50 Comment(0)
V
0

Just another thing to check if you're encountering the same 404 error as OP. I fiddled with lots of things, but finally the solution came down to merely adding the namespace to my service web.config.

So plain old ServiceFoo and IServiceFoo did NOT work:

  <services>
     <service behaviorConfiguration="quuxBehavior" name="ServiceFoo">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpsBinding" contract="IServiceFoo"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
     </service>
  </services>

But adding the namespace (ProjectBar) DID work:

  <services>
     <service behaviorConfiguration="quuxBehavior" name="ProjectBar.ServiceFoo">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpsBinding" contract="ProjectBar.IServiceFoo"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
     </service>
  </services>
Vouvray answered 5/8, 2014 at 16:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.