【问题标题】:Can several WCF services share a common BaseAddress?多个 WCF 服务可以共享一个公共 BaseAddress 吗?
【发布时间】:2009-01-12 13:42:48
【问题描述】:

我有一个包含多个 WCF 服务的程序集,每个服务都有自己的合同。这一切都很好。该服务的 app.config 中的服务配置如下所示:

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

由于我有一个更大的项目,有更多的合同,我想有办法在不同的服务合同之间共享 BaseAddress。
如果这只是一个具有不同合约和端点的服务,我可以设置一个通用基地址,但是如何为多个服务设置一个通用基地址?

当然,我需要为客户提供类似的东西。

【问题讨论】:

    标签: wcf app-config endpoints base-address


    【解决方案1】:

    您可以将所有合约合并到一个类中,这样您就拥有一个带有基地址的服务和每个合约一个(或多个)端点。

    为了避免拥有一个大的类文件,您可以使用部分关键字(假设您使用 c#)将类拆分到多个文件中。每个文件可以实现一个合约,这使得维护各个接口变得更加容易。

    在 C++ 中,您可以使用#includes 或多重继承,但这意味着大量的纪律...

    你的配置应该是这样的:

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

    【讨论】:

    • 好主意!唯一的问题是:部分 ServiceAll 类会很大,有很多很多的方法。
    • 没错。目前,除了切换到基于代码的实例化之外,我没有其他解决方案。
    【解决方案2】:

    服务可以共享 BaseAddress 值(包括端口号,如果 Net.Tcp 端口共享服务正在运行)。端点地址必须是唯一的。请注意,在您的配置文件中,每个 ServiceHost 的 MEX 端点的地址为“mex”。您的其他端点的地址为空字符串。当您向 WCF 提供端点的相对地址时(至少在配置文件中),基地址会附加到它的前面。因此,LogReader 服务的 MEX 端点地址为“net.tcp://localhost:8731/Design_Time_Addresses/SamAlyza/LogReader/mex”。

    由于未在主服务端点上设置相对地址,因此将 ServiceHost 的基地址用作主服务端点的实际地址。因为没有两个端点可以有重叠的 Uri.AbsolutePath 值,所以您的示例会让您相信基地址值不能共享。托管 WCF 服务的 ServiceHost 类没有内置终结点,而 ServiceEndpoint 类有一个 ListenUri 属性,该属性将根据您提供的设置进行填充。

    如果您将示例中的 baseAddress 值更改为全部匹配,只要您在 Endpoint 元素上设置唯一的相对地址值,一切都会正常工作。但是,您似乎可能会在使用 MEX 端点时遇到一些挑战,因为它们目前都有地址“mex”。让那些独一无二的,你应该没问题。

    现在,我必须问,您确定您不只是希望这些服务共享一个命名空间,而不是基地址吗?

    【讨论】:

    • 另一点是 baseAddress 只不过是当前位置,可以这么说。这个想法是所有端点通常都相对于baseAddress。因此,如果您尝试在所有服务之间共享相同的 baseAddress,您将限制您的部署选项。
    • 如果您正在寻找一种使配置更容易的方法,您将不得不改用代码而不是配置接线。您可以以编程方式创建 ServiceHost 和 ServiceEndpoint 实例,也可以从数据库中提取 Uri.AbsolutPath 值。
    • 是的,我正在寻找一种使配置文件更容易更改的方法。因此,如果您对此有任何想法,我会全力以赴。
    • 再问一个关于基于代码的 WCF 服务实例化的问题,我会发布一个示例静态类。
    • 我将发布一个问题,然后发布我的解决方案。
    【解决方案3】:

    如果您使用自定义的 ServiceHostFactory,您还可以在代码中设置基址。

    在配置中你可以有一些应用设置:

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

    然后自定义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);
        }
    
    }
    

    那么您还必须更改 .svc 文件才能使用该工厂:

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

    【讨论】:

      猜你喜欢
      • 2019-12-03
      • 2019-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-27
      • 2018-10-07
      • 1970-01-01
      相关资源
      最近更新 更多