C# – WCF can’t find the endpoint configuration issue

cconfigurationwcfwcf-bindingwcf-client

I have a webservice with WCF I'm testing on my local machine that's giving me a headscratcher.

My service is configured like so:

<system.serviceModel>
   <services>
      <service name="GHMDatroseIntegration.GHMDatroseWCFService.DatroseService" 
               behaviorConfiguration="DatroseServiceBehavior">
         <endpoint 
             address="mex"
             binding="basicHttpBinding" 
             contract="GHMDatroseIntegration.GHMDatroseWCFService.IDatroseService" />
      </service>
   </services>
   <behaviors>
      <serviceBehaviors>
         <behavior name="DatroseServiceBehavior">
            <serviceMetadata httpGetEnabled="true"/>
            <serviceDebug includeExceptionDetailInFaults="true"/>
            <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
         </behavior>
      </serviceBehaviors>
   </behaviors>
   <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

My client is configured like so:

<system.serviceModel>
   <bindings>
      <basicHttpBinding>
         <binding name="BasicHttpBinding_IDatroseService" 
             closeTimeout="00:02:00" openTimeout="00:01:00" 
             receiveTimeout="00:10:00" sendTimeout="00:02:00"
             allowCookies="false" bypassProxyOnLocal="false" 
             hostNameComparisonMode="StrongWildcard"
             maxBufferSize="524288" maxBufferPoolSize="524288" 
             maxReceivedMessageSize="524288" 
             messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
             useDefaultWebProxy="true">
            <readerQuotas 
                 maxDepth="32" maxStringContentLength="524288" 
                 maxArrayLength="524288" maxBytesPerRead="524288" 
                 maxNameTableCharCount="524288" />
            <security mode="None">
                 <transport clientCredentialType="None" proxyCredentialType="None"
                            realm="" />
                 <message clientCredentialType="UserName" algorithmSuite="Default" />
            </security>
         </binding>
      </basicHttpBinding>
   </bindings>
   <client>
       <endpoint name="BasicHttpBinding_IDatroseService"
           address="http://localhost/DatroseWCFService/DatroseService.svc"  
           behaviorConfiguration="DatroseServiceBehavior"
           binding="basicHttpBinding"  
           bindingConfiguration="BasicHttpBinding_IDatroseService"
           contract="DatroseWCFService.IDatroseService"  />
   </client>
   <behaviors>
      <endpointBehaviors>
         <behavior name="DatroseServiceBehavior">
             <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
         </behavior>
      </endpointBehaviors>
   </behaviors>
 </system.serviceModel>

The error I receive is:

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

… and yet, if I browse to the location I get the service screen, so it appears to be set up properly.

I'm sure this has do do with my configuration of the endpoints, but I can't figure out what they are supposed to look like. Some help would be appreciated here.

UPDATE whups I put the wrong error message in. It's fixed now.

UPDATE 2 per what I believe has been suggested in these responses I have changed my server config to :

<system.serviceModel>
   <services>
      <service name="GHMDatroseIntegration.GHMDatroseWCFService.DatroseService" 
               behaviorConfiguration="DatroseServiceBehavior">
         <endpoint 
             address="/svc"
             binding="basicHttpBinding"
             contract="GHMDatroseIntegration.GHMDatroseWCFService.IDatroseService"  />
         <endpoint 
             address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
       </service>
   </services>
   <behaviors>
       <serviceBehaviors>
          <behavior name="DatroseServiceBehavior">
             <serviceMetadata httpGetEnabled="true"/>
             <serviceDebug includeExceptionDetailInFaults="true"/>
             <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
          </behavior>
       </serviceBehaviors>
   </behaviors>
   <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

and my client configuration to:

<system.serviceModel>
   <bindings>
      <basicHttpBinding>
         <binding name="BasicHttpBinding_IDatroseService" 
             closeTimeout="00:02:00" openTimeout="00:01:00" 
             receiveTimeout="00:10:00" sendTimeout="00:02:00"
             allowCookies="false" bypassProxyOnLocal="false" 
             hostNameComparisonMode="StrongWildcard"
             maxBufferSize="524288" maxBufferPoolSize="524288" 
             maxReceivedMessageSize="524288"
             messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
             useDefaultWebProxy="true">
          <readerQuotas 
              maxDepth="32" maxStringContentLength="524288" maxArrayLength="524288"
              maxBytesPerRead="524288" maxNameTableCharCount="524288" />
          <security mode="None">
              <transport clientCredentialType="None" proxyCredentialType="None"
                        realm="" />
              <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
       </binding>
     </basicHttpBinding>
   </bindings>
   <client>
      <endpoint name="BasicHttpBinding_IDatroseService" 
          address="http://localhost/DatroseWCFService/DatroseService.svc/svc" 
          behaviorConfiguration="DatroseServiceBehavior"
          binding="basicHttpBinding" 
          bindingConfiguration="BasicHttpBinding_IDatroseService"
          contract="DatroseWCFService.IDatroseService" />
   </client>
   <behaviors>
      <endpointBehaviors>
         <behavior name="DatroseServiceBehavior">
            <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
         </behavior>
      </endpointBehaviors>
   </behaviors>
</system.serviceModel>

and when I run this I now get a 400 (bad request) error. I am not sure if this is a step forward or a step back. Have I created a new problem, or have I cleared my way to the next problem?

UPDATE 3

Upon niao' advice, I changed to this for the server config:

<system.serviceModel>
    <services>
        <service name="GHMDatroseIntegration.GHMDatroseWCFService.DatroseService" behaviorConfiguration="DatroseServiceBehavior">
            <endpoint contract="GHMDatroseIntegration.GHMDatroseWCFService.IDatroseService" binding="basicHttpBinding" address="http://localhost/DatroseWCFService/DatroseService.svc"/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="DatroseServiceBehavior">
                <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
                <serviceMetadata httpGetEnabled="true"/>
                <!-- 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"/>
                <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

…however, when I browsed to this address, I got a yellow screen of death:

Server Error in '/DatroseWCFService' Application.
When 'system.serviceModel/serviceHostingEnvironment/multipleSiteBindingsEnabled'
is set to true in configuration, the endpoints are required to specify
a relative address. If you are specifying a relative listen URI on the
endpoint, then the address can be absolute. To fix this problem,
specify a relative uri for endpoint
'http://localhost/DatroseWCFService/DatroseService.svc'.

…so with that, I tried making it a relative path like so:

<endpoint 
   address="localhost/DatroseWCFService/DatroseService.svc"
   binding="basicHttpBinding" 
   contract="GHMDatroseIntegration.GHMDatroseWCFService.IDatroseService" />

… but after publishing that, I get the 404 error. The client endpoint is configured as such:

<endpoint name="BasicHttpBinding_IDatroseService"
    address="http://localhost/DatroseWCFService/DatroseService.svc" 
    behaviorConfiguration="DatroseServiceBehavior"
    binding="basicHttpBinding" 
    bindingConfiguration="BasicHttpBinding_IDatroseService"
    contract="DatroseWCFService.IDatroseService"  />

UPDATE 4
Per marc_s' advice, I removed the binding config from the client, so my config looks like this:

<system.serviceModel>
    <client>
        <endpoint address="http://localhost/DatroseWCFService/DatroseService.svc" behaviorConfiguration="DatroseServiceBehavior"
         binding="basicHttpBinding" 
         contract="DatroseWCFService.IDatroseService" name="BasicHttpBinding_IDatroseService" />
    </client>
    <behaviors>
        <endpointBehaviors>
            <behavior name="DatroseServiceBehavior">
                <dataContractSerializer maxItemsInObjectGraph="10000000"/>
            </behavior>
        </endpointBehaviors>
    </behaviors>
</system.serviceModel>

and my server configuration looks like this:

<system.serviceModel>
    <services>
        <service name="GHMDatroseIntegration.GHMDatroseWCFService.DatroseService" behaviorConfiguration="DatroseServiceBehavior">
            <endpoint contract="GHMDatroseIntegration.GHMDatroseWCFService.IDatroseService" binding="basicHttpBinding" address=""/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="DatroseServiceBehavior">
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="true" httpsHelpPageEnabled="true" httpHelpPageEnabled="true"/>
                <dataContractSerializer maxItemsInObjectGraph="10000000"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

I no longer get the 404 error.

However, I do get a 400 (ProtocolException, Bad Request) with no edifying information of what it got or why it's bad. I expect I've progressed beyond the endpoint issue, into a brand new void of service configuration hell.

UPDATE 5

Per request, the "skeleton" of my service (I assume the interface will do?):

[ServiceContract]
public interface IDatroseService
{

    [OperationContract]
    bool SubmitPayableTransaction(List<InvoiceItem> invoices);

    [OperationContract]
    Dictionary<string, bool> ValidateAccounts(List<string> accounts);

    [OperationContract]
    Dictionary<string, int> GetVendor1099Types(List<string> vendors);

    [OperationContract]
    Dictionary<string, string> GetPaymentTerms(List<string> vendors);

}

Best Answer

So I assume your service is hosted inside IIS, right??

So the virtual directory where your *.svc lives basically defines your service address - so is this address correct?

Also: you have "relative" address of mex on the service endpoint

<endpoint 
    address="mex" 

(which I believe is a really bad idea - MEX stands for Metadata Exchange, and I would not use that address for a regular service endpoint! It just violates the Principle of Least Surprise - if the endpoint is called MEX, I expect it to BE a metadata exchange endpoint - not a regular service endpoint...)

Anyway - with that regular address, your complete service address becomes:

http://yourserver/DatroseWCFService/DatroseService.svc/mex

What if you call your service on that address - do you get a response??

Update: not sure how you're trying to test this. This is a SOAP web service - you will see the "landing page" (the "help" page) for the service in your browser, but to test the service itself, you need to use a SOAP capable testing tool (like the WCF Test Client or SoapUI) - you cannot test the SOAP web service by just browsing to its web address .
(ok, so your testing this by invoking the service from a test app - that should definitely work!)

Update #2: since you're hosting this in IIS (right?), your service address is basically defined by the virtual directory where your *.svc file lives. So my next attempt would be: just let that address be your service address.

Change your service-side config to:

<service name="GHMDatroseIntegration.GHMDatroseWCFService.DatroseService" 
         behaviorConfiguration="DatroseServiceBehavior">
   <endpoint 
       address=""   <!-- define nothing here - just let the *.svc file determine your service address -->
       binding="basicHttpBinding" 
       contract="GHMDatroseIntegration.GHMDatroseWCFService.IDatroseService" />
   <endpoint 
       address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>

and your client-side config to:

<endpoint name="BasicHttpBinding_IDatroseService"
    address="http://localhost/DatroseWCFService/DatroseService.svc" 
    behaviorConfiguration="DatroseServiceBehavior"
    binding="basicHttpBinding" 
    bindingConfiguration="BasicHttpBinding_IDatroseService"
    contract="DatroseWCFService.IDatroseService"  />

Does that work??

The next attempt would be to use the client-side config without a bindingConfiguration= value - since that's what you're doing on the server, too - just absolutely bare-bones basicHttpBinding without any modifications - does that work??

Related Topic