WCF, ChannelFactory, "Не удалось найти элемент конечной точки..."

Я пытаюсь вызвать службу WCF из другой службы, частично используя пример, который я нашел здесь на Stackru, который реализует ChannelFactory.

Я создал отдельный проект консольного приложения в своем решении для тестирования (VS 2008, кстати),

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
            }
        }
    }
}

Это из файла App.Config локальной службы, показывающего конечную точку:

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

Это из собственного App.Config тестового проекта:

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

Это метод, который я представил в моей локальной службе, которая, в свою очередь, передает объект запроса удаленной службе:

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;
}

Я получаю сообщение об ошибке:

Не удалось найти элемент конечной точки с именем " ServiceSoap " и контрактом " ServiceReference.ServiceSoap " в разделе конфигурации клиента ServiceModel. Это может быть связано с тем, что для вашего приложения не найден файл конфигурации или из-за того, что в клиентском элементе не найден элемент конечной точки, соответствующий этому имени.


Я запутался, где именно мне не хватает элемента конечной точки, в app.config для локальной службы (для которой определена ссылка на службу, указывающая на удаленную службу), app.config для тестового приложения или где-то еще?!


ОБНОВЛЕНИЕ: я нашел своего рода обходной путь после прочтения этой статьи MSDN, или я думаю, просто другой способ создания экземпляра ChannelFactory:

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

Вместо того, чтобы пытаться получить несуществующую или неправильную информацию в моем app.config, я вместо этого вручную вставляю значения для Binding (BasicHttpBinding) и адрес для удаленной службы. Это, кажется, помогает мне избежать ошибки "Не удалось найти элемент конечной точки", но я не уверен, что это лучшее решение.

1 ответ

Решение

Итак, в коде вашего тестового приложения вы запрашиваете элемент конечной точки с именем "ServiceSoap":

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

но в вашей конфигурации нет такой конечной точки:

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

Конфигурация содержит элемент конечной точки с именем "BasicHttpBinding_IServiceContract" (определяется name= атрибут на вашем <endpoint> узел).

Так что либо вы изменяете строку в своем тестовом приложении, чтобы запросить этот элемент конечной точки:

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

или вы измените свой app.config для тестового приложения, чтобы использовать ServiceSoap в качестве имени:

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

Любой из двух должен решить вашу проблему.

В вашем "обычном" клиентском приложении это работает, потому что, когда вы создаете клиентский прокси, вы вообще не указываете имя элемента конечной точки - WCF будет использовать только один единственный элемент, который присутствует. Если у вас должно быть более одного элемента конечной точки (например, с использованием разных протоколов), этот вызов без указания того, какой элемент конечной точки использовать, вызовет исключение, и вам придется изменить его, чтобы указать, какой элемент конечной точки (по его имени) использовать, тоже.

Другие вопросы по тегам