views:

2497

answers:

2

I've got a simple WCF service that works great on localhost - consumed by another local website and is returning data.

Now I upload my service to our host, changing the appropriate addresses in the web.config, and it breaks when the client calls it.

Error: The Address property on ChannelFactory.Endpoint was null. The ChannelFactory's Endpoint must have a valid Address specified.

I've read several other posts and I believe I've done pretty much all there was to do - setting the bindings, etc.

Below is my web.config for my wcf service (hosted through SSL):

<?xml version="1.0"?>
<!--
    Note: As an alternative to hand editing this file you can use the 
    web admin tool to configure settings for your application. Use
    the Website->Asp.Net Configuration option in Visual Studio.
    A full list of settings and comments can be found in 
    machine.config.comments usually located in 
    \Windows\Microsoft.Net\Framework\v2.x\Config 
-->
<configuration>
  <configSections>
    <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
        <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
        <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
          <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/>
          <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
          <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
          <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
        </sectionGroup>
      </sectionGroup>
    </sectionGroup>
  </configSections>
  <appSettings/>
  <connectionStrings/>
  <system.web>
    <!--
            Set compilation debug="true" to insert debugging 
            symbols into the compiled page. Because this 
            affects performance, set this value to true only 
            during development.
        -->
    <compilation debug="true">
      <buildProviders>
      </buildProviders>
      <assemblies>
        <add assembly="System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
        <add assembly="System.ServiceModel.Web, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
        <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      </assemblies>
    </compilation>
    <!--
            The <authentication> section enables configuration 
            of the security authentication mode used by 
            ASP.NET to identify an incoming user. 
    -->
    <authentication mode="Windows"/>
    <!--
            The <customErrors> section enables configuration 
            of what to do if/when an unhandled error occurs 
            during the execution of a request. Specifically, 
            it enables developers to configure html error pages 
            to be displayed in place of a error stack trace.

        <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
            <error statusCode="403" redirect="NoAccess.htm" />
            <error statusCode="404" redirect="FileNotFound.htm" />
        </customErrors>
        -->
    <customErrors mode="Off"></customErrors>
    <pages>
      <controls>
        <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      </controls>
    </pages>
    <httpHandlers>
      <!-- handlers for non IIS7 - IIS7 handlers are in system.webServer/handlers - below -->
      <remove verb="*" path="*.svc"/>
      <add verb="*" path="*.svc" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" validate="false"/>
      <remove verb="*" path="*.asmx"/>
      <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/>
    </httpHandlers>
    <httpModules>
      <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add name="ServiceModel" type="System.ServiceModel.Activation.HttpModule, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
    </httpModules>
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <providerOption name="CompilerVersion" value="v3.5"/>
        <providerOption name="WarnAsError" value="false"/>
      </compiler>
    </compilers>
  </system.codedom>
  <system.web.extensions>
    <scripting>
      <webServices>
        <!--
              Uncomment this section to enable the authentication service. Include 
              requireSSL="true" if appropriate.

          <authenticationService enabled="true" requireSSL = "true|false"/>
          -->
        <!--
              Uncomment these lines to enable the profile service, and to choose the 
              profile properties that can be retrieved and modified in ASP.NET AJAX 
              applications.

          <profileService enabled="true"
                          readAccessProperties="propertyname1,propertyname2"
                          writeAccessProperties="propertyname1,propertyname2" />
          -->
        <!--
              Uncomment this section to enable the role service.

          <roleService enabled="true"/>
          -->
      </webServices>
      <!--
        <scriptResourceHandler enableCompression="true" enableCaching="true" />
        -->
    </scripting>
  </system.web.extensions>
  <!--
        The system.webServer section is required for running ASP.NET AJAX under Internet
        Information Services 7.0.  It is not necessary for previous version of IIS.
    -->
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules>
      <add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    </modules>
    <handlers>
      <!-- handler for IIS 7 -->
      <add name=".svc" verb="*" path="*.svc" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
      <remove name="WebServiceHandlerFactory-Integrated"/>
      <remove name="ScriptHandlerFactory"/>
      <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <remove name="ScriptHandlerFactoryAppServices"/>
      <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <remove name="ScriptResource"/>
      <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    </handlers>
  </system.webServer>
  <system.serviceModel>
    <bindings>
      <!-- HTTP web binding -->
      <wsHttpBinding>
        <binding name="wsHttp">
          <security mode="None"/>
        </binding>
      </wsHttpBinding>
      <!-- HTTPS web binding -->
      <webHttpBinding>
        <binding name="wsHttps">
          <security mode="Transport"/>
        </binding>
      </webHttpBinding>
    </bindings>
    <!-- serviceHostingEnvironment aspNetCompatibilityEnabled="true" / -->
    <services>
      <service name="Service" behaviorConfiguration="ServiceBehavior">
        <!-- Service Endpoints -->
        <host>
          <baseAddresses>
            <add baseAddress="https://myserverssl.com/Service.svc"/&gt;
          </baseAddresses>
        </host>
        <endpoint address="https://myserverssl.com/"
                  binding="webHttpBinding"
                  bindingConfiguration="wsHttps"
                  behaviorConfiguration="webBehavior"
                  contract="IService">
          <!-- 
              Upon deployment, the following identity element should be removed or replaced to reflect the 
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
              automatically.
          -->
          <identity>
            <dns value="https://myserverssl.com"/&gt;
          </identity>
        </endpoint>
        <!-- endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/ -->
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="webBehavior">
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="false"
                           httpsGetEnabled="true"
                           httpsGetUrl="https://myserverssl.com/Service.svc"/&gt;
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Below is the config for the client:

<?xml version="1.0"?>
<!-- 
    Note: As an alternative to hand editing this file you can use the 
    web admin tool to configure settings for your application. Use
    the Website->Asp.Net Configuration option in Visual Studio.
    A full list of settings and comments can be found in 
    machine.config.comments usually located in 
    \Windows\Microsoft.Net\Framework\v2.x\Config 
-->
<configuration>
    <configSections>
     <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
       <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
       <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
        <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/>
        <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
        <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
        <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
       </sectionGroup>
      </sectionGroup>
     </sectionGroup>
    </configSections>
    <appSettings/>
    <connectionStrings/>
    <system.web>
     <!-- 
            Set compilation debug="true" to insert debugging 
            symbols into the compiled page. Because this 
            affects performance, set this value to true only 
            during development.
        -->
     <compilation debug="true">
      <assemblies>
       <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
       <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
       <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
       <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
      </assemblies>
     </compilation>
     <!--
            The <authentication> section enables configuration 
            of the security authentication mode used by 
            ASP.NET to identify an incoming user. 
        -->
     <authentication mode="Windows"/>
     <!--
            The <customErrors> section enables configuration 
            of what to do if/when an unhandled error occurs 
            during the execution of a request. Specifically, 
            it enables developers to configure html error pages 
            to be displayed in place of a error stack trace.

        <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
            <error statusCode="403" redirect="NoAccess.htm" />
            <error statusCode="404" redirect="FileNotFound.htm" />
        </customErrors>
        -->
     <pages>
      <controls>
       <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
       <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      </controls>
     </pages>
     <httpHandlers>
      <remove verb="*" path="*.asmx"/>
      <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/>
     </httpHandlers>
     <httpModules>
      <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
     </httpModules>
    </system.web>
    <system.codedom>
     <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
       <providerOption name="CompilerVersion" value="v3.5"/>
       <providerOption name="WarnAsError" value="false"/>
      </compiler>
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4" type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
       <providerOption name="CompilerVersion" value="v3.5"/>
       <providerOption name="OptionInfer" value="true"/>
       <providerOption name="WarnAsError" value="false"/>
      </compiler>
     </compilers>
    </system.codedom>
    <!-- 
        The system.webServer section is required for running ASP.NET AJAX under Internet
        Information Services 7.0.  It is not necessary for previous version of IIS.
    -->
    <system.webServer>
     <validation validateIntegratedModeConfiguration="false"/>
     <modules>
      <remove name="ScriptModule"/>
      <add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
     </modules>
     <handlers>
      <remove name="WebServiceHandlerFactory-Integrated"/>
      <remove name="ScriptHandlerFactory"/>
      <remove name="ScriptHandlerFactoryAppServices"/>
      <remove name="ScriptResource"/>
      <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
     </handlers>
    </system.webServer>
    <runtime>
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
       <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/>
       <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
      </dependentAssembly>
      <dependentAssembly>
       <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/>
       <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
      </dependentAssembly>
     </assemblyBinding>
    </runtime>
    <system.serviceModel>
     <bindings>
       <customBinding>
        <binding name="WebHttpBinding_IService">
         <!--    WsdlImporter encountered unrecognized policy assertions in ServiceDescription 'http://tempuri.org/':    -->
         <!--    <wsdl:binding name='WebHttpBinding_IService'>    -->
         <!--        <sp:HttpsToken xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"&gt;..&lt;/sp:HttpsToken&gt;    -->
         <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
          messageVersion="Soap12" writeEncoding="utf-8">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
           maxBytesPerRead="4096" maxNameTableCharCount="16384" />
         </textMessageEncoding>
        </binding>
       </customBinding>
    </bindings>
     <client>
   <endpoint binding="customBinding" bindingConfiguration="WebHttpBinding_IService"
    contract="ServiceReference1.IService" name="WebHttpBinding_IService" address="https://myserverssl.com/Service.svc" />
  </client>
    </system.serviceModel>
</configuration>

I added the address attribute and am now getting the following error:

The CustomBinding on the ServiceEndpoint with contract 'IService' lacks a TransportBindingElement. Every binding must have at least one binding element that derives from TransportBindingElement.

Line 113:        
Line 114:        public string GetData(int value) {
Line 115:            return base.Channel.GetData(value);
Line 116:        }
Line 117:

If someone can please shed some light on this, that would be great!

A: 

I'm pretty sure that Endpoint address shouldn't be a full address, it's relative to the Foobar.svc file (so, usually '/'). I haven't ever had to put the fully qualified URL into my web.config.

Paul Betts
no, actually in IIS - the svc file and its location (on server and in a virtual directory) **IS** the address - nothing is based on anything else.
marc_s
+1  A: 

Well, the error message really says it all:

Every binding must have at least one binding element that derives from TransportBindingElement.

The custom binding you defined only has a textMessageEncoding element - that's only half the story! As the error say - you must also add a transport element to it:

<customBinding>
   <binding name="WebHttpBinding_IService">
     <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
         messageVersion="Soap12" writeEncoding="utf-8">
         <readerQuotas maxDepth="32" maxStringContentLength="8192" 
                       maxArrayLength="16384" maxBytesPerRead="4096" 
                       maxNameTableCharCount="16384" />
     </textMessageEncoding>
     <httpTransport />
   </binding>
</customBinding>

See the new <httpTransport/> element? I'm never sure whether it needs to be first before the encoding, or after it - try it out, one of the two situations will work :-)

If you're hosting with SSL, you might need to use <httpsTransport /> instead.

Now, your custom binding should be complete to use.

Additionally, however - on your server side, you only have a "webHttpBinding" endpoint - but on the client, you are trying to connect to an endpoint that has "customBinding" enabled..... you need to make up your mind - those things need to match between server and client! On the server side, define the same endpoint you want to try to connect to from the client - otherwise it'll never work....

Also, since you're hosting in IIS, this setting of a base address is totally useless and won't do anything - just strip it out!

<service name="Service" behaviorConfiguration="ServiceBehavior">
    <host>
      <baseAddresses>
        <add baseAddress="https://myserverssl.com/Service.svc"/&gt;
      </baseAddresses>
    </host>

The address of the service is always determine by server name (or IP), name of the virtual directory and the svc file inside that virtual directory - you cannot change that, you cannot modify that, you cannot influence that.

marc_s
Great thanks! Looks like I'm getting closer now. I added the httpstransport, and webHttpBinding with security mode="transport" to the client's web.config. I'm now getting "Manual addressing is enabled on this factory, so all messages sent must be pre-addressed." The factory I used (see link above) handles multiple host headers. I'm fairly new to this, so any help is greatly appreciated.
ElHaix