Question

J'ai un assemblage contenant plusieurs services WCF, chacun avec son propre contrat. Tout fonctionne bien. La configuration du service dans app.config pour le service ressemble à ceci:

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

Étant donné que j'ai un projet plus important en tête, avec plus de contrats, j'aimerais pouvoir partager l'adresse de base entre les différents contrats de service.
S'il ne s'agit que d'un service avec des contrats et des points de terminaison différents, je pourrais définir une robe de base commune, mais comment puis-je définir une robe de base commune pour plusieurs services?

Bien sûr, il me faudrait quelque chose de similaire pour le client.

Était-ce utile?

La solution

Vous pouvez combiner tous les contrats dans une même classe. Vous disposez ainsi d'un service avec une adresse de base et d'un (ou plusieurs) terminal (s) par contrat.

Pour éviter d'avoir un fichier de classe volumineux, vous pouvez utiliser le mot-clé partial (si vous utilisez c #) pour diviser la classe en plusieurs fichiers. Chaque fichier peut implémenter un contrat, ce qui facilite grandement la maintenance des interfaces individuelles.

En C ++, vous pouvez utiliser #includes ou un héritage multiple, mais cela implique une grande discipline ...

Votre configuration ressemblerait à ceci:

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

Autres conseils

Les services peuvent partager les valeurs de BaseAddress (y compris les numéros de port, si le service de partage de port Net.Tcp est en cours d'exécution). Ce sont les adresses des points d'extrémité qui doivent être uniques. Notez dans votre fichier de configuration que les noeuds finaux MEX de chaque ServiceHost ont une adresse "mex". Vos autres points de terminaison ont une adresse de chaîne vide. Lorsque vous fournissez une adresse relative pour un noeud final à WCF (au moins dans le fichier de configuration), l'adresse de base lui est ajoutée. Par conséquent, l'adresse de point de terminaison MEX du service LogReader est "net.tcp: // localhost: 8731 / Add_Heure_Des_Time_Design / SamAlyza / LogReader / mex".

Puisqu’une adresse relative n’a pas été définie sur le noeud final de service principal, l’adresse de base de ServiceHost est utilisée comme adresse réelle pour le noeud final de service principal. Etant donné que deux noeuds finaux ne peuvent pas avoir de valeurs Uri.AbsolutePath se chevauchant, votre exemple vous ferait croire que les valeurs d'adresse de base ne peuvent pas être partagées. La classe ServiceHost qui héberge des services WCF n'a pas de point de terminaison intégré, alors que la classe ServiceEndpoint a une propriété ListenUri qui sera renseignée en fonction des paramètres que vous fournissez.

Si vous modifiez les valeurs baseAddress de votre exemple pour toutes les correspondances, tant que vous définissez des valeurs d'adresse relative uniques sur les éléments Endpoint, tout devrait fonctionner. Cependant, il semble que vous rencontriez des difficultés avec les points de terminaison MEX, car ils portent tous l'adresse "mex". actuellement. Rendez-les uniques et ça devrait aller.

Maintenant, je dois demander, êtes-vous sûr de ne pas simplement vouloir que ces services partagent un espace de noms plutôt que des adresses de base?

Vous pouvez également définir les adresses de base dans le code si vous utilisez un ServiceHostFactory personnalisé.

Dans la configuration, vous pouvez définir certains paramètres d'application:

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

Créez ensuite un ServiceHostFactory personnalisé:

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

}

Ensuite, vous devez également modifier vos fichiers .svc pour utiliser cette usine:

<%@ ServiceHost Language="C#" Debug="true" Service="MyApp.MyService" CodeBehind="MyService.svc.cs" Factory="MyApp.MyServiceHostFactory" %>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top