Использовать веб-сервис SOAP, не полагаясь на app.config - PullRequest
32 голосов
/ 13 сентября 2010

Я создаю компонент .NET, который будет вызывать внешний веб-сервис.Я использовал диалоговое окно «Добавить ссылку на службу», чтобы добавить веб-службу к своему компоненту, которая генерирует код, необходимый для использования службы, и добавляет настройки в файл app.config.

Я тестирую компонентдобавив ссылку на его DLL из консольного приложения и вызвав соответствующий метод, который создает новый экземпляр веб-службы: ... = new MyServiceSoapClient().Однако, когда я делаю это, я получаю следующее исключение:

InvalidOperationException

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

Это имеет смысл, так как app.config не используетсяпринес с DLL компонента.Как я могу позвонить в веб-сервис, не полагаясь на настройки в App.Config?

Ответы [ 3 ]

69 голосов
/ 14 сентября 2010

Настройки в <system.ServiceModel> в файле app.config сообщат компоненту, как подключиться к внешнему веб-сервису. Xml - это просто текстовое представление необходимых классов и перечислений, необходимых для подключения по умолчанию к веб-службе.

Например, это код, который был сгенерирован для веб-сервиса, который я добавил:

<system.serviceModel>
 <bindings>
  <basicHttpBinding>
   <binding name="MyServicesSoap" closeTimeout="00:01:00" openTimeout="00:01:00"
     receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
     bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
     maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
     messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
     useDefaultWebProxy="true">
     <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
       maxBytesPerRead="4096" maxNameTableCharCount="16384" />
     <security mode="None">
      <transport clientCredentialType="None" proxyCredentialType="None"
        realm="" />
      <message clientCredentialType="UserName" algorithmSuite="Default" />
     </security>
    </binding>
   </basicHttpBinding>
  </bindings>
 <client>
  <endpoint address="http://services.mycompany.com/WebServices/MyServices.asmx"
    binding="basicHttpBinding" bindingConfiguration="MyServicesSoap"
    contract="MyServices.MyServicesSoap" name="MyServicesSoap" />
 </client>
</system.serviceModel>

Это можно перевести в код, например, так:

    'Set up the binding element to match the app.config settings '
    Dim binding = New BasicHttpBinding()
    binding.Name = "MyServicesSoap"
    binding.CloseTimeout = TimeSpan.FromMinutes(1)
    binding.OpenTimeout = TimeSpan.FromMinutes(1)
    binding.ReceiveTimeout = TimeSpan.FromMinutes(10)
    binding.SendTimeout = TimeSpan.FromMinutes(1)
    binding.AllowCookies = False
    binding.BypassProxyOnLocal = False
    binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard
    binding.MaxBufferSize = 65536
    binding.MaxBufferPoolSize = 524288
    binding.MessageEncoding = WSMessageEncoding.Text
    binding.TextEncoding = System.Text.Encoding.UTF8
    binding.TransferMode = TransferMode.Buffered
    binding.UseDefaultWebProxy = True

    binding.ReaderQuotas.MaxDepth = 32
    binding.ReaderQuotas.MaxStringContentLength = 8192
    binding.ReaderQuotas.MaxArrayLength = 16384
    binding.ReaderQuotas.MaxBytesPerRead = 4096
    binding.ReaderQuotas.MaxNameTableCharCount = 16384

    binding.Security.Mode = BasicHttpSecurityMode.None
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None
    binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None
    binding.Security.Transport.Realm = ""
    binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName
    binding.Security.Message.AlgorithmSuite = Security.SecurityAlgorithmSuite.Default

    'Define the endpoint address'
    Dim endpointStr = "http://services.mycompany.com/WebServices/MyServices.asmx"
    Dim endpoint = New EndpointAddress(endpointStr)
    'Instantiate the SOAP client using the binding and endpoint'
    'that were defined above'
    Dim client = New MyServicesSoapClient(binding, endpoint)

Обычно, когда вы используете конструктор без параметров (т.е. new MyServicesSoapClient()), будут использоваться настройки в файле app.config. Однако вы можете обойти файл app.config, явно установив значения binding и endpoint в коде и передав эти экземпляры в конструктор.

0 голосов
/ 15 февраля 2018

Настройка конфигурации Binding и Endpoint в коде - это один из способов, но есть другой способ использовать потребительскую DLL и оставить конфигурацию в существующем файле App.config.

Причина, по которой возникает упомянутое InvalidOperationException , заключается в том, что в DLL нет параметров конфигурации. Он всегда полагается на App.config, чтобы обеспечить его, но, поскольку вы используете DLL в другом консольном приложении, он не находит параметры конфигурации.

Когда мы используем диалоговое окно «Добавить ссылку на службу» для добавления веб-службы к клиентскому компоненту и создания экземпляра веб-службы, мы позволяем Visual Studio обрабатывать создание канала связи и загружать параметр конфигурации. Так что, если мы мы можем создать такой канал самостоятельно, тогда мы сможем управлять настройками конфигурации.

Microsoft предоставляет классы для этой цели, ConfigurationChannelFactory<TChannel> Класс - один. MSDN заявляет:

Предоставляет общие функциональные возможности для создания элемента конфигурации канала для определенного типа.

ConfigurationChannelFactory позволяет централизованно управлять конфигурацией клиента WCF.

Используйте диалоговое окно «Добавить ссылку на службу», чтобы добавить веб-службу к клиентскому компоненту, так как нам нужен экземпляр интерфейса служебного канала.

Сначала переименуйте созданный файл App.config в App.dll.config и в его Свойствах файла измените Копировать в Выходной каталог свойство в Копировать всегда

Создайте класс, у которого есть метод, который возвращает объект Channel для доступа к веб-службе, например:

public class ManageService
{
    public static T CreateServiceClient<T>(string configName)
    {
        string _assemblyLocation = Assembly.GetExecutingAssembly().Location;
        var PluginConfig = ConfigurationManager.OpenExeConfiguration(_assemblyLocation);
        ConfigurationChannelFactory<T> channelFactory = new ConfigurationChannelFactory<T>(configName, PluginConfig, null);
        var client = channelFactory.CreateChannel();
        return client;
    }
}

Поскольку мы установили свойство Copy Always VS, копируем DLL проекта, а также файл App.dll.config в папку bin . Assembly.GetExecutingAssembly().Location вернуть место сборки и ConfigurationManager.OpenExeConfiguration

Открывает указанный файл конфигурации клиента как объект конфигурации.

PluginConfig содержит файл конфигурации App.Config Object, а ConfigurationChannelFactory<T> использует его для связи со службой.

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

Client = ManageService.CreateServiceClient<SampleService.IKeyServiceChannel>("MetadataExchangeTcpBinding_IKeyService"); 

SampleService - это пространство имен моего веб-сервиса. Client содержит экземпляр веб-службы.

Если вам нужно обработать Duplex Communication и Callbacks, тогда вы можете посмотреть на ConfigurationDuplexChannelFactory<TChannel> Class.

0 голосов
/ 13 сентября 2010

Если это служба WCF (как это звучит из сообщений об ошибках), то, по большей части, вам понадобится что-то - app.config, потому что это app.config, который сообщает остальным WCF о том, что MyServiceSoapClient является веб-службой (с небольшим изменением в двух файлах app.config это может стать именованной службой канала без перекомпиляции кода ....)

Теперь, если вы действительно хотите сделать это без app.config, вам нужно выбросить сгенерированный MyServiceSoapClient() и написать свой собственный, основываясь на HttpWebRequest.

...