WCF over SSL - 404 error

48,828

Solution 1

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)

Solution 2

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.

Solution 3

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

Share:
48,828
eidylon
Author by

eidylon

Software developer working primarily in VB.NET, C# and Sql Server. Occasionally working in ORACLE. I love RegEx and jQuery, and have just started playing around with WebAPI. Hobbyist prop maker. Have created several Mass Effect replica weapons as well as a number of custom-designed commission pieces. Projects and pictures on my Facebook page... https://www.facebook.com/darkchannelprops

Updated on January 29, 2021

Comments

  • eidylon
    eidylon over 3 years

    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>
    
  • eidylon
    eidylon over 14 years
    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.
  • Rama
    Rama over 10 years
    Yes serviceName fixed this for me
  • Rocklan
    Rocklan about 10 years
    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.