WCF, ChannelFactory, "Could not find endpoint element..."

Darth Continent picture Darth Continent · Dec 30, 2009 · Viewed 17.9k times · Source

I'm trying to call a WCF service from within another service, in part using an example I found here on StackOverflow which implements ChannelFactory.

I've created a separate console app project within my solution for testing (VS 2008, btw),

namespace MyService.Test
{
    class Program
    {
        static void Main(string[] args)
        {
            MySolution.MyTestClient proxy = new MyTestClient();

            proxy = new MyTestClient();
            proxy.Endpoint.Address = new EndpointAddress("http://localhost:8723/MySolution/");

            // Instantiate a request object and assign values to its member variables.    
            MySolution.RemoteServiceMethod() theObject = new RemoteServiceMethod();            
            theObject.SomeProperty = "123";
            theObject.SomeOtherProperty = "alpha";

            Console.WriteLine("Calling the remote service method now...");

            try
            {
                proxy.SubmitRemoteServiceRequest(proxy.theObject);
            }
            catch (FaultException<MySolution.RequestException> e)
            {
                // exception code hereMySolution
            }
        }
    }
}

This is from the local service's App.Config showing the endpoint:

<system.serviceModel>
  <client>
   <endpoint address="http://MyService/MyService.asmx"
     binding="basicHttpBinding" bindingConfiguration="ServiceSoap"
     contract="ServiceReference.ServiceSoap"
     name="ServiceSoap" />
  </client>
  ...
 </system.serviceModel>  

This is from the test project's own App.Config:

 <client>
      <endpoint address="http://localhost:8723/MyService"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IServiceContract"
        contract="ServiceContract.IServiceContract" name="BasicHttpBinding_IServiceContract" />
 </client>  

This is the method I've exposed in my local service, which in turn passes a request object to the remote service:

public ServiceContract.Response.ZZZ_Response SubmitRemoteServiceRequest(ServiceContract.Request.ZZZ_Request sc_TheirServiceRequest)
{
     var factory = new ChannelFactory<ServiceReference.ServiceSoap>("ServiceSoap");
     var wcfClient = factory.CreateChannel();
     bool closedSuccessfully = false;

     // Instantiate a response object which I will return to the consumer.
     ServiceContract.Response.ZZZ_Response zzz_Response = new ServiceContract.Response.ZZZ_Response();

     // Instantiate request and response objects, respectively, which I use internal to my service to call remote service.
     ServiceReference.MyServiceRequest scMyServiceRequest = new ServiceReference.MyServiceRequest();

     ServiceReference.MyServiceResponse scMyServiceResponse = new ServiceReference.MyServiceResponse();

     try
     {                
          // Now you can make calls on the wcfClient object
          scMyServiceResponse = wcfClient.MyServiceMethod(scMyServiceRequest );                

          ((ICommunicationObject)wcfClient).Close();
          closedSuccessfully = true;
     }
     finally
     {
          if (!closedSuccessfully)
          {
               ((ICommunicationObject)wcfClient).Abort();
          }
     }

     return zzz_Response;
}

The error I receive is this:

Could not find endpoint element with name 'ServiceSoap' and contract 'ServiceReference.ServiceSoap' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this name could be found in the client element.


I'm confused, where exactly am I missing the endpoint element, in the app.config for the local service (which has a Service Reference defined that points to the remote service), the app.config for the test app, or elsewhere?!


UPDATE: I found a workaround of sorts after reading this MSDN article, or I guess just a different way of instantiating the ChannelFactory:

var factory = new ChannelFactory<ServiceReference.ServiceSoap>(new BasicHttpBinding(), "http://urlToRemoteService/RemoteService.asmx");

Instead of trying to grab from nonexistent or incorrect info in my app.config, I'm instead manually plugging in the values for the Binding (BasicHttpBinding), and the address to the remote service. This seems to get me past the "Could not find endpoint element" error, but I'm not sure if this is the best solution.

Answer

marc_s picture marc_s · Dec 30, 2009

Well, in your test app's code, you request the endpoint element by the name of "ServiceSoap":

 var factory = new ChannelFactory<ServiceReference.ServiceSoap>("ServiceSoap");

but in your config, there's no such endpoint:

 <client>
      <endpoint address="http://localhost:8723/DelinquencyService"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IServiceContract"
        contract="ServiceContract.IServiceContract" name="BasicHttpBinding_IServiceContract" />
 </client>  

The config contains an endpoint element by the name of "BasicHttpBinding_IServiceContract" (defined by the name= attribute on your <endpoint> node).

So either you change the line in your test app to request that endpoint element:

 var factory = new ChannelFactory<ServiceReference.ServiceSoap>("BasicHttpBinding_IServiceContract");

or you change your app.config for the test app to use ServiceSoap as the name:

<client>
   <endpoint name="ServiceSoap"
        address="http://localhost:8723/DelinquencyService"
        binding="basicHttpBinding" 
        bindingConfiguration="BasicHttpBinding_IServiceContract"
        contract="ServiceContract.IServiceContract" />
</client>  

Either of the two should solve your problem.

In your "normal" client app, this works because when you create the client proxy, you don't specify an endpoint element name at all - WCF will just use the one and only element that's present. If you should have more than one endpoint element (e.g. using different protocols), this call without specifying which endpoint element to use would throw an exception, and you'd have to change it to specify which endpoint element (by its name) to use, too.