Can several WCF services share a common BaseAddress?

倖福魔咒の 提交于 2019-12-18 11:11:30

问题


I've got an assembly containing several WCF services, each with its own contract. It all works nicely. The service config in the app.config for the service looks like this:

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

Since I've got a bigger project in mind, with more contracts, I'd like to have a way to share the BaseAddress between the different service contracts.
If this would just be one service with different contracts and endpoints, I could set a ommon baseaddress, but how do I set a common baseaddress for more than one service?

Of course I'd need something similar for the client.


回答1:


You can combine all contracts in one class, so you have one service with a baseaddress and one (or more) endpoint(s) per contract.

To avoid having one large class-file you can use the partial-keyword (asuming you use c#) to split the class across multiple files. Each file can implement one contract, that makes maintaining the individual interfaces much easier.

In C++ you can use #includes or multiple inheritance, but that imply a large amount of discipline...

Your config would look like this:

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



回答2:


Services can share BaseAddress values (including port #'s, if the Net.Tcp Port Sharing Service is running). It's the endpoint addresses that must be unique. Notice in your config file that the MEX endpoints for each ServiceHost have an address of "mex". Your other endpoints have an address of empty string. When you provide a relative address for an endpoint to WCF (in the config file at least), the base address is prepended to it. Therefore, the MEX endpoint address for the LogReader service is "net.tcp://localhost:8731/Design_Time_Addresses/SamAlyza/LogReader/mex".

Since a relative address was not set on the main service endpoint, the base address of the ServiceHost is used as the actual address for the main service endpoint. Because no two endpoints can have overlapping Uri.AbsolutePath values, your example would lead you to believe that base address values cannot be shared. The ServiceHost class that hosts WCF services does not have a built-in endpoint, whereas the ServiceEndpoint class has a ListenUri property that will be populated based on the settings you provide.

If you change the baseAddress values in your example to all match, as long as you set unique relative address values on the Endpoint elements, everything should work. However, it appears that you may run into some challenges with the MEX endpoints, since they all have the address "mex" currently. Make those unique and you should be fine.

Now, I must ask, are you sure that you are not simply wanting these services to share a namespace, rather than base addresses?




回答3:


You can also set the base addresses in code if you use a custom ServiceHostFactory.

In config you can have some app setting:

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

Then make a custom ServiceHostFactory:

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

}

Then you also have to change your .svc files to use that factory:

<%@ ServiceHost Language="C#" Debug="true" Service="MyApp.MyService" CodeBehind="MyService.svc.cs" Factory="MyApp.MyServiceHostFactory" %>


来源:https://stackoverflow.com/questions/435423/can-several-wcf-services-share-a-common-baseaddress

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!