WCF, ChannelFactory, "Не удалось найти элемент конечной точки..."
Я пытаюсь вызвать службу WCF из другой службы, частично используя пример, который я нашел здесь, в StackOverflow, который реализует ChannelFactory.
Я создал отдельный проект консольного приложения в своем решении для тестирования (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
}
}
}
}
Это из локальной службы 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 для тестового приложения, или в другом месте?!
ОБНОВЛЕНИЕ. Я обнаружил, что после этого
Вместо того, чтобы пытаться захватить несуществующую или некорректную информацию в моем app.config, вместо этого я вручную подключаю значения для привязки (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>
node).
Итак, либо вы меняете строку в тестовом приложении, чтобы запросить этот элемент конечной точки:
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 будет использовать только тот и тот единственный элемент, который присутствует. Если у вас должно быть несколько элементов конечной точки (например, с использованием разных протоколов), этот вызов без указания того, какой элемент конечной точки будет использоваться, генерирует исключение, и вам придется изменить его, чтобы указать, какой элемент конечной точки (по его названию) использовать, тоже.