多个 WCF 服务可以共享一个公共 BaseAddress 吗?

发布于 2024-07-11 19:55:34 字数 2282 浏览 4 评论 0原文

我有一个包含多个 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。
如果这只是一项具有不同合约和端点的服务,我可以设置一个通用基地址,但如何为多个服务设置一个通用基地址?

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

π浅易 2024-07-18 19:55:34

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

为了避免出现一个大的类文件,您可以使用partial-关键字(假设您使用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>

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>
冬天的雪花 2024-07-18 19:55:34

服务可以共享 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”。 让它们变得独一无二,你应该没问题。

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

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?

貪欢 2024-07-18 19:55:34

如果您使用自定义 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" %>

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" %>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文