2013-07-09 10 views
6

Ho un servizio Web WCF remoto a cui mi sto connettendo dalla mia applicazione.Garantire che le richieste WCF in uscita vengano eseguite utilizzando un'interfaccia di rete specifica

La domanda può essere in esecuzione su un server con più indirizzi IP (o più interfacce di rete fisiche)

ho bisogno di fare in modo che posso controllare che l'indirizzo IP viene utilizzato per la richiesta in uscita, invece di utilizzando l'interfaccia 'preferita' secondo le normali regole metriche.

Il motivo è che più copie del software verranno eseguite sulla stessa macchina, ciascuna associata a un indirizzo IP specifico per le proprie operazioni e il servizio remoto connesso a deve sapere quale viene utilizzato per collegarsi di nuovo ad esso in un secondo momento (dal momento che ottenere l'indirizzo sbagliato significa collegarsi al servizio sbagliato)

Con i servizi legacy ASMX questo viene fatto ignorando GetWebRequest(Uri uri) sulla classe parziale generata per il servizio. Ma non riesco a capire come farlo con WCF.

Su un unrelated SO post, MVP @JohnSaunders ha suggerito che ciò potrebbe essere possibile assumendo l'intero meccanismo di trasporto utilizzato da WCF. Ma non ho ancora capito come farlo.

+0

Informazioni su http://stackoverflow.com/questions/3249846/specify-the-outgoing-ip-ad-ress-to-use-with-wcf-client –

+0

@BradChristie La prima risposta è a livello di SO, la seconda risposta non si applica a WCF e si applica solo alle richieste SOAP non elaborate, quindi perché la domanda non ha una risposta accettata. – PhonicUK

+2

BTW, in base all'indirizzo IP per decidere a quale istanza connettersi è ... una soluzione non ottimale. –

risposta

3

Questa è una difficile problema, che WCF non sembra soddisfare particolarmente bene.

L'unico componente nel framework .NET che sembra gestire direttamente il problema relativo all'indirizzo del client è la classe ServicePoint. Nello specifico, ha una proprietà BindIPEndPointDelegate che ti consente di controllare come seleziona l'IP del client. La documentazione per la proprietà comprende questo:

tecniche di bilanciamento

Alcuni di carico richiedono un client per utilizzare un indirizzo IP e numero di porta specifico locale, piuttosto che IPAddress.Any (o IPAddress.IPv6Any per Internet Protocol Version 6) e una porta effimera. Il tuo BindIPEndPointDelegate può soddisfare questo requisito.

Pertanto, si dovrebbe essere in grado di modificare il punto di servizio associato con il vostro URL in codice come questo:

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

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

Ovviamente questo tipo di codice richiede la vostra classi hanno la consapevolezza del protocollo e l'indirizzo dell'endpoint il cliente comunicherà con.Sarebbe probabilmente più appropriato impostare questa logica come un comportamento client che può essere applicato al tuo canale client.

+1

Suppongo che tu stia utilizzando HTTP, dal momento che hai menzionato i servizi ASMX. Questa soluzione funziona solo per il protocollo HTTP, poiché ServicePointManager gestisce solo tale stack. –

0

è possibile utilizzare una proprietà di messaggio (HttpRequestMessageProperty) per aggiungere intestazioni HTTP a qualsiasi richiesta in uscita. È necessario creare un "ambito" in cui la proprietà verrà aggiunta al "contesto operativo" corrente e allegare la proprietà, con tutte le intestazioni desiderate, alle proprietà dei messaggi in uscita del contesto.

si prega di guardare a questo:

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

0

Utilizzare questa: Nuova Classe :

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

E adesso è qualcosa di simile:

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