views:

1953

answers:

5

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 http**s**://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 http**s**://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"/&gt;
        </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>
A: 

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

marc_s
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.
eidylon
+1  A: 

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/"/&gt;
        </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>
eidylon
... 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.
Program.X
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.
eidylon
+1  A: 

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>
Greg
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!
Wil P
A: 

Try adding /soap at the end of the service URL.

Rodrigo Rodriguez
A: 

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)

John Ketchpaw