2009-09-25 14 views
8

Ho un set di Contratti di servizio che suddividono la mia interfaccia di servizio in blocchi di funzionalità correlate. Attualmente sto implementando tutti i contratti usando una singola classe di servizio (potrebbe volerli suddividere in seguito, ma per ora è sufficiente la singola classe di servizio).WCF Servizio ospitato da IIS più Contratti di servizio implementati da un singolo servizio: come posso condividere uri tra endpoint tramite config

Sto cercando di utilizzare configurare gli endpoint utilizzando un file di configurazione (anziché tramite il codice). Il problema è che ho un ServiceActivationException perché i due endpoint (uno per ogni contratto di servizio) stanno cercando di ascoltare sullo stesso uri. I dettagli di eccezione dicono che per raggiungere questo obiettivo i due endpoint devono condividere l'oggetto vincolante, il che ha senso, ma non riesco a capire come farlo tramite config (non ho provato a farlo via codice come sto ospitando in IIS ma Posso immaginare che sia un semplice esercizio configurare in codice).

che segue è la configurazione Attualmente sto usando (questo è ancora dev quindi non sono attualmente preoccupati per problemi di sicurezza ecc, che alcune di queste impostazioni possono esporre):

<system.serviceModel> 
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> 
<services> 
    <service name="CDC.WebPortal.MidTier.MidTierAccessService" 
      behaviorConfiguration="MidTierServiceBehaviour" > 
    <endpoint address="" 
       binding="webHttpBinding" 
       bindingConfiguration="RestBindingConfiguration" 
       contract="****************************.IProductService" /> 

    <endpoint address="" 
       binding="webHttpBinding" 
       bindingConfiguration="RestBindingConfiguration" 
       contract="****************************.ICategoryService" /> 

    <endpoint address="mex" binding="mexHttpBinding" 
       contract="IMetadataExchange" /> 

    </service> 
</services> 

<bindings> 
    <webHttpBinding> 
    <binding name="RestBindingConfiguration" 
      maxReceivedMessageSize="104857600"> 
     <readerQuotas maxStringContentLength="104857600"/> 
    </binding> 
    </webHttpBinding> 
</bindings> 

<behaviors> 
    <serviceBehaviors> 
    <behavior name="MidTierServiceBehaviour"> 
     <serviceMetadata httpGetEnabled="true" /> 
     <serviceDebug includeExceptionDetailInFaults="false" /> 
    </behavior> 
    </serviceBehaviors> 
</behaviors> 

Quindi la mia domanda è: come posso condividere questo legame tra i due endpoint?

I commenti in this SO question suggeriscono che potrebbe non essere in grado di farlo, ma non credo che sia corretto.

UPDATE 1 Secondo this MS publication quello che sto facendo dovrebbe essere ok ...

UPDATE2 Ecco il contenuto del file SVC se aiuta:

<%@ ServiceHost Language="VB" Debug="true" 
       Service="*********************.MidTierAccessService" 
       Factory="Microsoft.ServiceModel.Web.WebServiceHost2Factory" %> 

UPDATE 3 Ecco il dettaglio delle eccezioni:

Un instante vincolante ce è già stato associato ad ascoltare URI '********************'. Se due endpoint vogliono condividere lo stesso ListenUri, devono anche condividere la stessa istanza di oggetto vincolante. I due endpoint in conflitto sono stati specificati nelle chiamate AddServiceEndpoint(), in un file di configurazione o in una combinazione di AddServiceEndpoint() e config.

AGGIORNAMENTO 4 Ok ho perso this prima, affermando "È necessario utilizzare indirizzi relativi quando si espone più di un punto finale per un particolare servizio .svc". La causa di questo è qualcosa che ha a che fare con la directory virtuale IIS che determina l'indirizzo di base del servizio, qualcuno può spiegarlo in modo un po 'più dettagliato, cioè perché IIS ha bisogno di indirizzamento relativo per ogni contratto.

risposta

7

Per quanto ne so, e ho svolto un lavoro approfondito con WCF nell'ultimo mese, non è possibile condividere lo stesso URI esatto per più di un endpoint. In WCF, un "servizio" non è definito dall'implementazione di un contratto, ma dal contratto stesso (che segue anche le pratiche WSDL e standard SOA). Gli endpoint consentono di esporre un singolo servizio tramite più protocolli (e quindi diversi indirizzi) , ma non puoi condividere servizi diversi con lo stesso indirizzo esatto. Logicamente questo non funzionerebbe.

Si supponga che il seguente scenario (che è quello che si sta cercando di realizzare):

IProductService exposed @ http://localhost/service 
ICategoryService exposed @ http://localhost/service 
IMetadataExchange exposed @ http://localhost/service/mex 

E 'abbastanza facile accedere l'endpoint MEX ... ha un unico URI. Tuttavia, come si accede a IProductService o ICategoryService? Non c'è nulla che ti permetta di differenziare i due diversi da un URI. WCF non ha nulla che gli consenta di instradare tra i messaggi che dovrebbero andare su IProductservice e quelli che dovrebbero andare su ICategoryService. Poiché entrambi utilizzano lo stesso URI, si ha effettivamente un conflitto. Ogni CONTRATTO di servizio deve essere esposto tramite un URI univoco. Ogni endpoint che utilizza la stessa associazione esatta deve utilizzare un indirizzo distinto.

C'è un modo per ottenere ciò di cui hai bisogno. Il problema è il routing dei messaggi. WCF non supporta nativamente il routing dei messaggi OOB, tuttavia fornisce la possibilità di implementare il proprio router di messaggi. (Oppure, se siete disposti ad usare la tecnologia beta, .NET 4.0 viene fornito con un router di messaggi, basato sugli articoli collegati sotto, ma con una migliore configurabilità.) Michele Bustamante, una vera strega di WCF, ha fornito un completa attuazione e articolo che descrive il routing dei messaggi ai seguenti link:

http://msdn.microsoft.com/en-us/magazine/cc500646.aspx http://msdn.microsoft.com/en-us/magazine/cc546553.aspx

L'idea generale è che si imposta un unico servizio che ascolta su un singolo URI. Questo servizio utilizza l'invio di caratteri jolly in un'unica operazione di servizio, che determina quale URI univoco per instradare ciascun messaggio. Puoi decidere come preferisci, ma il più semplice è tramite la richiesta Azione, assumendo che ogni azione sulle tue due interfacce, IProductService e ICategoryService, siano globalmente uniche. Si finirà con più servizi, tuttavia ... il router stesso è un servizio WCF distinto che dovrebbe essere ospitato come qualsiasi altro.

+2

+1 per "vera maga" – dan

+0

@dan: lol: D Grazie. – jrista

Problemi correlati