2013-07-09 12 views
6

Ich habe einen WCF-Web-Remote-Dienst, zu dem ich eine Verbindung mit meiner Anwendung herstelle.Sicherstellen, dass ausgehende WCF-Anforderungen mithilfe einer bestimmten Netzwerkschnittstelle ausgeführt werden

Die Anwendung auf einem Server mit mehreren IP-Adressen (oder mehreren physikalischen Netzwerkschnittstellen)

Ich muß sicherstellen, dass ich Adresse steuern kann für die Outbound-Anforderung verwendet wird, anstatt nur die IP kann ausgeführt werden, Verwenden der "bevorzugten" Schnittstelle gemäß den normalen Metrikregeln.

Der Grund dafür ist, dass mehrere Kopien der Software auf demselben Computer ausgeführt werden, wobei jeder für seine eigenen Operationen an eine bestimmte IP-Adresse gebunden ist und der entfernte Dienst wissen muss, welcher Server verwendet wird um zu einem späteren Zeitpunkt eine Verbindung zu ihm herzustellen (da das Abrufen der Adresse eine Verbindung mit dem falschen Dienst erfordert)

Bei älteren ASMX-Diensten wird dies durch Überschreiben von GetWebRequest(Uri uri) für die für den Dienst generierte Teilklasse ausgeführt. Aber ich kann überhaupt nicht herausfinden, wie man das mit WCF macht.

Auf einem unrelated SO post schlug MVP @JohnSaunders dies möglicherweise durch Übernahme des gesamten von WCF verwendeten Transportmechanismus vor. Aber ich habe auch noch nicht herausgefunden, wie ich das machen soll.

+0

Wie wäre es mit http://stackoverflow.com/questions/3249846/specify-the-outgoing-ip-address-to-use-with-wcf-client –

+0

@BradChristie Die erste Antwort ist OS-Ebene, die zweite Antwort doesn Sie gelten nicht für WCF und gelten nur für SOAP-Anfragen, weshalb diese Frage keine akzeptierte Antwort hat. – PhonicUK

+2

BTW, abhängig von der IP-Adresse zu entscheiden, welche Instanz zu verbinden ist ... eine suboptimale Lösung. –

Antwort

3

Dies ist eine schwierige Problem, auf das WCF nicht besonders gut zu reagieren scheint.

Die einzige Komponente in .NET Framework, das sich mit der Frage des Client Adresse ist die ServicePoint Klasse direkt zu beschäftigen scheint. Insbesondere verfügt es über eine BindIPEndPointDelegate-Eigenschaft, mit der Sie steuern können, wie die Client-IP ausgewählt wird. Die Dokumentation für die Eigenschaft enthält diese:

Einige Load-Balancing-Techniken einen Client erfordert eine bestimmte lokale IP-Adresse und Portnummer zu verwenden, anstatt IPAddress.Any (oder IPAddress.IPv6Any für Internet Protocol Version 6) und einem temporären Port. Ihr BindIPEndPointDelegate kann diese Anforderung erfüllen.

Daher sollten Sie in der Lage sein, den Service-Point mit Ihrer URL in Code wie folgt zugeordnet zu ändern:

var servicePoint = ServicePointManager.FindServicePoint(
    new Uri("http://contoso.com/service.svc")); 

servicePoint.BindIPEndPointDelegate = 
    (sp, remote, retryCount) => new IPEndPoint(address, portNumber); 

Offensichtlich ist diese Art von Code erfordert Ihre Klassen haben das Bewusstsein für das Protokoll und die Endpunktadresse Der Kunde wird mit kommunizieren.Es wäre wahrscheinlich am besten, diese Logik als Client-Verhalten einzurichten, das auf Ihren Client-Kanal angewendet werden kann.

+1

Ich gehe davon aus, dass Sie HTTP verwenden, da Sie ASMX-Dienste erwähnt haben. Diese Lösung funktioniert nur für das HTTP-Protokoll, da ServicePointManager nur mit diesem Stack arbeitet. –

0

Sie können eine Nachrichteneigenschaft (HttpRequestMessageProperty) verwenden, um ausgehende HTTP-Header zu allen ausgehenden Anfragen hinzuzufügen. Sie müssen einen "Bereich" erstellen, in dem die Eigenschaft zum aktuellen "Operationskontext" hinzugefügt wird, und die Eigenschaft mit allen gewünschten Headern an die Eigenschaften der ausgehenden Nachrichten des Kontexts anhängen.

bitte an aussehen:

how-to-override-getwebrequest-method-using-service-reference-instead-of-web-reference-in-wcf

0

Verwenden Sie diese: Neue Klasse:

using System.Web.Services.Protocols; 
using System.Windows.Forms; 
using System; 

public static class ExtensionMethods 
{ 
    public static string ApplyServerURL(this SoapHttpClientProtocol service) 
    { 
     try 
     { 
      string name = service.GetType().Name; 
      return string.Format("{0}{1}.svc", Settings.Instance.ServerAddress, name); 
     } 
     catch 
     { return string.Empty; } 
    } 
} 

Und jetzt ist so etwas wie dieses:

YourService us = new YourService(); 
us.Url = us.ApplyServerURL();