Domanda

Ho un assembly contenente diversi servizi WCF, ognuno con il proprio contratto. Funziona tutto bene. Il servizio config in app.config per il servizio è simile al seguente:

<services>
  <service behaviorConfiguration="WcfService.AlyzaServiceBehavior"
    name="Sam.Alyza.WcfService.ServiceWebsites">
    <endpoint address="" binding="netTcpBinding" contract="Sam.Alyza.WcfInterface.IServiceWebsites">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:8731/Design_Time_Addresses/SamAlyza/Websites/" />
      </baseAddresses>
    </host>
  </service>
  <service behaviorConfiguration="Sam.Alyza.WcfService.LogReaderServiceBehavior"
    name="Sam.Alyza.WcfService.ServiceLogReader">
    <endpoint address="" binding="netTcpBinding" contract="Sam.Alyza.WcfInterface.IServiceLogReader">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:8731/Design_Time_Addresses/SamAlyza/LogReader/" />
      </baseAddresses>
    </host>
  </service>
  <service behaviorConfiguration="Sam.Alyza.WcfService.ServiceSystemverwaltungBehavior"
    name="Sam.Alyza.WcfService.ServiceSystemverwaltung">
    <endpoint address="" binding="netTcpBinding" contract="Sam.Alyza.WcfInterface.IServiceSystemverwaltung">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:8731/Design_Time_Addresses/SamAlyza/Systemverwaltung/" />
      </baseAddresses>
    </host>
  </service>
  [...]
</services>

Dato che ho in mente un progetto più grande, con più contratti, vorrei avere un modo per condividere BaseAddress tra i diversi contratti di servizio.
Se questo fosse solo un servizio con contratti ed endpoint diversi, potrei impostare un indirizzo di base comune, ma come posso impostare un indirizzo di base comune per più di un servizio?

Ovviamente avrei bisogno di qualcosa di simile per il cliente.

È stato utile?

Soluzione

Puoi combinare tutti i contratti in una classe, quindi hai un servizio con un indirizzo di base e uno (o più) endpoint (s) per contratto.

Per evitare di avere un file di classe di grandi dimensioni è possibile utilizzare la parola chiave parziale (supponendo che si usi c #) per dividere la classe su più file. Ogni file può implementare un contratto, il che rende molto più semplice la manutenzione delle singole interfacce.

In C ++ puoi usare #includes o ereditarietà multipla, ma ciò implica una grande quantità di disciplina ...

La tua configurazione sarebbe simile a questa:

<services>
  <service behaviorConfiguration="WcfService.AlyzaServiceBehavior"
    name="Sam.Alyza.WcfService.ServiceAll">
    <endpoint address="Websites/" binding="netTcpBinding" contract="Sam.Alyza.WcfInterface.IServiceWebsites">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="LogReader/" binding="netTcpBinding" contract="Sam.Alyza.WcfInterface.IServiceLogReader">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="Systemverwaltung/" binding="netTcpBinding" contract="Sam.Alyza.WcfInterface.IServiceSystemverwaltung">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:8731/Design_Time_Addresses/SamAlyza/" />
      </baseAddresses>
    </host>
  </service>
</services>

Altri suggerimenti

I servizi possono condividere i valori BaseAddress (compresi i numeri di porta, se il servizio di condivisione delle porte Net.Tcp è in esecuzione). Sono gli indirizzi degli endpoint che devono essere univoci. Si noti nel file di configurazione che gli endpoint MEX per ciascun ServiceHost hanno un indirizzo di " mex " ;. Gli altri endpoint hanno un indirizzo di stringa vuota. Quando si fornisce un indirizzo relativo per un endpoint a WCF (almeno nel file di configurazione), l'indirizzo di base viene anteposto ad esso. Pertanto, l'indirizzo dell'endpoint MEX per il servizio LogReader è " net.tcp: // localhost: 8731 / Design_Time_Addresses / SamAlyza / LogReader / mex " ;.

Poiché non è stato impostato un indirizzo relativo sull'endpoint del servizio principale, l'indirizzo base di ServiceHost viene utilizzato come indirizzo effettivo per l'endpoint del servizio principale. Poiché non è possibile che due valori finali si sovrappongano con valori Uri.AbsolutePath, il tuo esempio ti indurrebbe a credere che i valori dell'indirizzo di base non possano essere condivisi. La classe ServiceHost che ospita i servizi WCF non ha un endpoint incorporato, mentre la classe ServiceEndpoint ha una proprietà ListenUri che verrà popolata in base alle impostazioni fornite.

Se si modificano i valori baseAddress nell'esempio in modo che corrispondano tutti, purché si impostino valori di indirizzo relativi univoci sugli elementi Endpoint, tutto dovrebbe funzionare. Tuttavia, sembra che potresti riscontrare alcune difficoltà con gli endpoint MEX, dal momento che tutti hanno l'indirizzo "mex" attualmente. Rendi quelli unici e dovresti andare bene.

Ora, devo chiederlo, sei sicuro di non voler semplicemente che questi servizi condividano uno spazio dei nomi, piuttosto che gli indirizzi di base?

Puoi anche impostare gli indirizzi di base nel codice se usi un ServiceHostFactory personalizzato.

In config puoi avere alcune impostazioni dell'app:

<configuration>
  <appSettings>
    <add key="BaseAddress" value="http://localhost:1234" />
  </appSettings>
<configuration>

Quindi crea una ServiceHostFactory personalizzata:

public sealed class MyServiceHostFactory : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        var baseAddy = ConfigurationManager.AppSettings["BaseAddress"];
        baseAddresses.Add(new Uri(baseAddy));
        return new ServiceHost(serviceType, baseAddresses);
    }

}

Quindi devi anche cambiare i tuoi file .svc per usare quella factory:

<%@ ServiceHost Language="C#" Debug="true" Service="MyApp.MyService" CodeBehind="MyService.svc.cs" Factory="MyApp.MyServiceHostFactory" %>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top