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

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

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

InvalidOperationException

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

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

3 ответа

Решение

Настройки в <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 значения в коде и передачи этих экземпляров в конструктор.

Установка конфигурации связывания и конечной точки в коде - это один из способов, но есть другой способ использовать потребительскую 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 содержит экземпляр веб-службы.

Если вам нужно обрабатывать дуплексную связь и обратные вызовы, вы можете посмотреть на ConfigurationDuplexChannelFactory<TChannel> Учебный класс.

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

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

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