it-swarm.com.de

Verbrauchen a SOAP Webservice, ohne sich auf die app.config zu verlassen

Ich baue eine .NET-Komponente, die einen externen Webdienst aufruft. Ich habe den Dialog "Dienstreferenz hinzufügen" verwendet, um den Webdienst meiner Komponente hinzuzufügen. Dieser generiert den Code, der für die Verwendung des Dienstes erforderlich ist, und fügt die Einstellungen der Datei app.config hinzu.

Ich teste die Komponente, indem Sie einen Verweis auf ihre DLL von einer Konsolenanwendung hinzufügen und die entsprechende Methode aufrufen, die eine neue Instanz des Webdiensts erstellt: ... = new MyServiceSoapClient(). Wenn ich das tue, bekomme ich jedoch die folgende Ausnahme:

InvalidOperationException 

Das Standardendpunktelement, das den Vertrag "MyServicesSoap" referenziert, konnte im Abschnitt "ServiceModel-Client-Konfiguration" nicht gefunden werden. Dies kann daran liegen, dass für Ihre Anwendung keine Konfigurationsdatei gefunden wurde oder dass kein Endpunktelement gefunden wurde, das mit diesem Vertrag übereinstimmt.

Dies ist sinnvoll, da die app.config nicht mit der DLL der Komponente übernommen wird. Wie kann ich den Webservice aufrufen, ohne sich auf die Einstellungen in App.Config verlassen zu müssen?

31
Ben McCormack

Die Einstellungen in <system.ServiceModel> in der Datei app.config geben der Komponente an, wie eine Verbindung zum externen Webdienst hergestellt werden soll. Die XML-Datei ist lediglich eine Textdarstellung der erforderlichen Klassen und Aufzählungen, um die Standardverbindung zum Webdienst herzustellen.

Dies ist beispielsweise der Code, der für den hinzugefügten Webdienst generiert wurde:

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

Dies kann wie folgt in Code übersetzt werden:

    '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)

Wenn Sie den parameterlosen Konstruktor (d. H. new MyServicesSoapClient()) verwenden, werden normalerweise die Einstellungen in der Datei app.config verwendet. Sie können die Datei app.config jedoch umgehen, indem Sie die Werte binding und endpoint explizit im Code festlegen und diese Instanzen in den Konstruktor übergeben.

68
Ben McCormack

Das Festlegen der Binding - und Endpoint -Konfiguration im Code ist eine Möglichkeit, aber es gibt eine andere Möglichkeit, den Consumer DLL zu verwenden und die Konfiguration in der vorhandenen App.config-Datei zu belassen.

Der Grund für die erwähnte InvalidOperationException ist, dass DLL die Konfigurationseinstellungen nicht enthält. Es ist immer auf App.config angewiesen, um es bereitzustellen. Da Sie jedoch die DLL in einer anderen Konsolenanwendung verwenden, werden die Konfigurationseinstellungen nicht gefunden.

Wenn wir das Dialogfeld "Dienstreferenz hinzufügen" verwenden, um den Webdienst der Clientkomponente hinzuzufügen und eine Instanz des Webdiensts zu erstellen, überlassen wir Visual Studio die Erstellung des Kommunikationskanals und laden die Konfigurationseinstellung. Wenn dies möglich ist Erstellen Sie einen solchen Kanal explizit, dann können wir die Konfigurationseinstellungen verwalten.

Microsoft stellt Klassen für diesen Zweck bereit, ConfigurationChannelFactory<TChannel> Klasse ist eine. MSDN gibt an:

Stellt die allgemeine Funktionalität zum Erstellen eines Kanalkonfigurationselements für einen bestimmten Typ bereit.

Die ConfigurationChannelFactory ermöglicht die zentrale Verwaltung der WCF-Client-Konfiguration.

Verwenden Sie das Dialogfeld "Dienstreferenz hinzufügen", um den Webdienst zur Clientkomponente hinzuzufügen, wenn Sie die Instanz des Service Channel Interface benötigen.

Benennen Sie zunächst die erzeugte Datei App.config in App.dll.config um und ändern Sie in ihren File-Eigenschaften die DateiCopy to Output Directoryin die Eigenschaft Copy Immer

Erstellen Sie eine Klasse, die über eine Methode verfügt, die das Channel-Objekt zurückgibt, um auf den Web-Service zuzugreifen.

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

Da wir die Eigenschaft Copy Always gesetzt haben, kopiert VS das Projekt DLL sowie die App.dll.config in den Ordner bin . Assembly.GetExecutingAssembly().Location gibt den Montageort und ConfigurationManager.OpenExeConfiguration zurück

Öffnet die angegebene Client-Konfigurationsdatei als Konfigurationsobjekt.

PluginConfig enthält die App.Config-Konfigurationsdatei Object und ConfigurationChannelFactory<T> verwendet sie zur Kommunikation mit dem Dienst.

Diese Methode kann aufgerufen werden, indem Sie Ihr Service Channel Interface-Objekt wie folgt übergeben:

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

SampleService ist der Namespace meines Webservice. Client enthält die Instanz des Web-Service.

Wenn Sie mit Duplex Communication und Callbacks arbeiten müssen, können Sie sich ConfigurationDuplexChannelFactory<TChannel> Class anschauen. 

0