WCF IIS托管服务多个服务合同由单个服务实现 - 如何通过配置共享端点之间的uri [英] WCF IIS hosted service multiple Service Contracts implemented by a single service - how do I share uri between endpoints via config

查看:581
本文介绍了WCF IIS托管服务多个服务合同由单个服务实现 - 如何通过配置共享端点之间的uri的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一组服务合同,将我的服务接口拆分成相关功能的块。我现在正在使用单一的服务类(可能想分裂这些后来,但现在单一服务类足够了)。



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



以下是我目前使用的配置(这仍然是dev,所以我目前不担心关于安全性问题等,这些设置中的一些可能暴露):

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



我共享两个端点之间的这种绑定?



这个SO问题表明我可能无法做到这一点,但我不认为这是正确的。



UPDATE 1 根据此MS发布,我



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

 <%@ ServiceHost Language =VBDebug =true
Service =************** *******。MidTierAccessService
Factory =Microsoft.ServiceModel.Web.WebServiceHost2Factory%>

UPDATE 3 以下是异常详细信息:


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


UPDATE 4 确定我错过了,说明当为特定.svc服务公开多个端点时,您将需要使用相对地址。这是因为IIS虚拟目录确定服务的基地址,任何人都可以更详细地解释这一点,即为什么IIS需要为每个合同的相对寻址。


<根据我的知识,我在上个月一直在与WCF做广泛的工作,你不能为多个端点共享相同的确切的URI。在WCF中,服务不是由合同的实现定义的,而是由合同本身定义的(也遵循WSDL和标准SOA实践)。端点允许您通过多个协议(以及为不同的地址)暴露单个服务, ,但您不能在相同的确切地址上共享不同的服务。



假设以下情况(这是您想要完成的):

  IProductService暴露@ http:// localhost / service 
ICategoryService暴露@ http:// localhost / service
IMetadataExchange暴露@ http:// localhost / service / mex

访问MEX端点很容易...它有一个唯一的URI。但是,如何访问IProductService或ICategoryService?没有什么可以让你区分两个而不是一个URI。 WCF没有任何东西,将允许它在应该去IProductservice的消息之间,以及那些应该去ICategoryService的消息之间路由。由于两者使用相同的URI,你确实有冲突。每个服务合同必须通过唯一的URI公开。使用相同的精确绑定的每个端点必须使用不同的地址。



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



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



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


I have a set of Service Contracts which split up my service interface into chunks of related functionality. I am currently implementing all contracts using a single service class (may want to split these later but for now the single service class suffices).

I am trying to use configure the endpoints using a config file (as opposed to via code). The problem is I get a ServiceActivationException because the two endpoints (one for each service contract) are trying to listen on the same uri. The exception details say that to achieve this the two endpoints must share the binding object, which makes sense but I can't figure out how to do this via config (I haven't tried doing this via code as I am hosting in IIS but I can imagine it being a simple exercise to configure in code).

The following is the config I am currently using (this is still dev so I'm not currently worried about security concerns etc. that some of these settings may expose):

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

So my question is how do I share this binding between the two endpoints?

Comments in this SO question suggest I may not be able to do this, but I don't beleive that is correct.

UPDATE 1 According to this MS publication what I'm doing should be ok...

UPDATE2 Here is the svc file content if it helps:

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

UPDATE 3 Here is the exception detail:

A binding instance has already been associated to listen URI '********************'. If two endpoints want to share the same ListenUri, they must also share the same binding object instance. The two conflicting endpoints were either specified in AddServiceEndpoint() calls, in a config file, or a combination of AddServiceEndpoint() and config.

UPDATE 4 Ok I missed this before, stating "You will need to use relative addresses when exposing more than one endpoint for a particular .svc service". The cause of this is something to do with the IIS virtual directory determining the base address of the service, can anyone explain this in a little more detail, i.e. why IIS needs relative addressing for each contract.

解决方案

To my knowledge, and I have been doing extensive work with WCF in the last month, you can not share the same exact URI for more than one endpoint. In WCF, a "service" is not defined by the implementation of a contract, but by the contract itself (which also follows WSDL and standard SOA practices.) Endpoints allow you to expose a single service via multiple protocols (and therefor different addresses), but you can not share different services on the same exact address. Logically that wouldn't work.

Assume the following scenario (which is what you are trying to accomplish):

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

It is easy enough to access the MEX endpoint...it has a unique URI. However, how do you access either of IProductService or ICategoryService? There is nothing that allows you to differentiate the two other than a URI. WCF has nothing that will allow it to route between messages that are supposed to go to IProductservice, and those that are supposed to go to ICategoryService. Since both use the same URI, you do indeed have a conflict. Every service CONTRACT must be exposed via a unique URI. Every endpoint that utilizes the same exact binding must use a distinct address.

There is a way to achieve what you need. The problem is message routing. WCF does not natively support message routing OOB, however it does provide the ability to implement your own message router. (Or, if you are willing to use beta tech, .NET 4.0 comes with a message router out of the box, based on the articles linked below, but with improved configurability.) Michele Bustamante, a veritable sorceress of WCF, has provided a complete implementation and article describing message routing at the following links:

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

The general idea is that you set up a single service that listens on a single URI. This service uses wildcard dispatch to a single service operation, which then determines which unique URI to route each message to. You can make the determination any way you wish, however the simplest is via the request Action, assuming each action on your two interfaces, IProductService and ICategoryService, are globally unique. You will end up with more services, however...the router itself is a distinct WCF service that would need to be hosted just like any other.

这篇关于WCF IIS托管服务多个服务合同由单个服务实现 - 如何通过配置共享端点之间的uri的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆