WCF IIS 托管服务由单个服务实现的多个服务合同 - 如何通过配置在端点之间共享 uri

Posted

技术标签:

【中文标题】WCF IIS 托管服务由单个服务实现的多个服务合同 - 如何通过配置在端点之间共享 uri【英文标题】:WCF IIS hosted service multiple Service Contracts implemented by a single service - how do I share uri between endpoints via config 【发布时间】:2010-12-01 07:08:31 【问题描述】:

我有一组服务合同,它们将我的服务接口分成相关功能块。我目前正在使用单个服务类实现所有合同(可能希望稍后拆分这些合同,但现在单个服务类就足够了)。

我正在尝试使用配置文件(而不是通过代码)来配置端点。问题是我得到了一个ServiceActivationException,因为两个端点(每个服务合同一个)试图监听同一个uri。异常细节说,要实现这一点,两个端点必须共享绑定对象,这是有道理的,但我不知道如何通过配置来做到这一点(我没有尝试通过代码来做到这一点,因为我在 IIS 中托管但是我可以想象这是一个在代码中配置的简单练习。

以下是我当前使用的配置(这仍然是开发,所以我目前不担心其中一些设置可能会暴露的安全问题等):

<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
  <service name="CDC.WebPortal.MidTier.MidTierAccessService"
           behaviorConfiguration="MidTierServiceBehaviour" >
    <endpoint address=""
              binding="webHttpBinding"
              bindingConfiguration="RestBindingConfiguration"
              contract="****************************.IProductService" />

    <endpoint address=""
              binding="webHttpBinding"
              bindingConfiguration="RestBindingConfiguration"
              contract="****************************.ICategoryService" />

    <endpoint address="mex" binding="mexHttpBinding"
              contract="IMetadataExchange" />

  </service>
</services>

<bindings>
  <webHttpBinding>
    <binding name="RestBindingConfiguration"
             maxReceivedMessageSize="104857600">
      <readerQuotas maxStringContentLength="104857600"/>
    </binding>
  </webHttpBinding>
</bindings>

<behaviors>
  <serviceBehaviors>
    <behavior name="MidTierServiceBehaviour">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="false" />
    </behavior>
  </serviceBehaviors>
</behaviors>

所以我的问题是如何在两个端点之间共享这个绑定?

this SO question 中的评论表明我可能无法做到这一点,但我不相信这是正确的。

更新 1 根据this MS publication 我正在做的应该没问题...

UPDATE2如果有帮助,这里是 svc 文件内容:

<%@ ServiceHost Language="VB" Debug="true"
                Service="*********************.MidTierAccessService"
                Factory="Microsoft.ServiceModel.Web.WebServiceHost2Factory" %>

更新 3 以下是异常详情:

绑定实例已关联到侦听 URI '********************'。如果 两个端点想要共享同一个 ListenUri,它们也必须共享同一个绑定 对象实例。两个冲突的端点要么在 AddServiceEndpoint() 调用,在配置文件中,或 AddServiceEndpoint() 的组合 和配置。

更新 4 好的,我之前错过了 this,指出“在为特定 .svc 服务公开多个端点时,您将需要使用相对地址”。造成这种情况的原因与确定服务基地址的 IIS 虚拟目录有关,任何人都可以更详细地解释一下,即为什么 IIS 需要对每个合同进行相对寻址。

【问题讨论】:

【参考方案1】:

据我所知,上个月我一直在使用 WCF 进行大量工作,您不能为多个端点共享相同的确切 URI。在 WCF 中,“服务”不是由合同的实现定义的,而是由合同本身定义的(也遵循 WSDL 和标准 SOA 实践)。端点允许您通过多个协议(因此使用不同的地址)公开单个服务,但您不能在同一个确切地址上共享不同的服务。从逻辑上讲,这是行不通的。

假设以下场景(这是您要完成的任务):

IProductService exposed @ http://localhost/service
ICategoryService exposed @ http://localhost/service
IMetadataExchange exposed @ http://localhost/service/mex

访问 MEX 端点很容易......它有一个唯一的 URI。但是,您如何访问 IProductService 或 ICategoryService?除了 URI 之外,没有任何东西可以让您区分两者。 WCF 没有任何东西允许它在应该发送到 IProductservice 的消息和应该发送到 ICategoryService 的消息之间进行路由。由于两者都使用相同的 URI,因此您确实存在冲突。每个服务合同都必须通过唯一的 URI 公开。每个使用相同精确绑定的端点都必须使用不同的地址。

有一种方法可以实现您所需要的。问题是消息路由。 WCF 本身并不支持消息路由 OOB,但它确实提供了实现您自己的消息路由器的能力。 (或者,如果您愿意使用 beta 技术,.NET 4.0 附带了一个开箱即用的消息路由器,基于下面链接的文章,但具有改进的可配置性。) WCF 名副其实的女巫 Michele Bustamante 提供了一个完整的实现和描述消息路由的文章在以下链接:

http://msdn.microsoft.com/en-us/magazine/cc500646.aspx http://msdn.microsoft.com/en-us/magazine/cc546553.aspx

一般的想法是您设置一个侦听单个 URI 的单个服务。此服务使用通配符分派到单个服务操作,然后确定将每条消息路由到哪个唯一 URI。您可以按照您希望的任何方式进行确定,但最简单的是通过请求操作,假设您的两个接口 IProductService 和 ICategoryService 上的每个操作都是全局唯一的。您最终会得到更多服务,但是...路由器本身是一个独特的 WCF 服务,需要像其他任何服务一样托管。

【讨论】:

以上是关于WCF IIS 托管服务由单个服务实现的多个服务合同 - 如何通过配置在端点之间共享 uri的主要内容,如果未能解决你的问题,请参考以下文章

由 IIS 7 和全局变量(单例)托管的 WCF 服务

WCF:单个服务的多个绑定配置

如何诊断由 IIS7 托管的 WCF 服务中的 W3WP.exe 错误

使用单个 Windows 服务托管 4 个不同的 WCF 项目。如何?

WCF net.tcp 绑定:托管多个服务是不是需要端口共享?

IIS托管WCF服务:集成测试和代码覆盖