WCF 服务在 2 个不同的服务合同上公开 2 个端点

Posted

技术标签:

【中文标题】WCF 服务在 2 个不同的服务合同上公开 2 个端点【英文标题】:WCF service exposing 2 endpoints on 2 different service contracts 【发布时间】:2012-11-24 09:22:19 【问题描述】:

我有一个 WCF 服务,我正在尝试对其进行配置,以便它公开 2 个端点,在不同的 URL 下引用不同的功能。

我想要的是 Service1,公开方法 A、B、C 和 Service2,公开方法 D、E。 我希望能够同时浏览 localhost/WebServiceName/Service1/Service.svclocalhost/WebServiceName/Service2/Service.svc

引用 localhost/WebServiceName/Service1/Service.svc 的其他应用程序应该只看到包含方法 A、B 和 C 的接口。它们应该看不到任何关于 Service2 的内容界面。对于 Service2 也是如此。

到目前为止,我已经在我的 WCF 服务中定义了两个接口,I_Service1I_Service2

我在 web.config 中添加了两个端点,如下所示:

<endpoint address="http://localhost/WebServiceName/Service1/" binding="wsHttpBinding" contract="WebServiceName.I_Service1" bindingConfiguration="Binding1" />
<endpoint address="http://localhost/WebServiceName/Service2/" binding="wsHttpBinding" contract="WebServiceName.I_Service2" bindingConfiguration="Binding2" />  

在enpoint中使用完整地址的建议来自这里:Multiple endpoints under IIS

但是,我仍然无法浏览 localhost/WebServiceName/Service1/Service.svc。我收到:

Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly. 

我可以成功浏览localhost/WebServiceName/Service.svc,并且wsdl包括方法A、B、C、D、E。但这在我想要的行为中应该是错误的。

我有什么遗漏的吗?

更新:在这篇文章http://allen-conway-dotnet.blogspot.ro/2011/09/exposing-multiple-binding-types-for.html 之后,我为这些端点创建了两个不同的合同服务。但目前我浏览它时只看到 Service1Service2 显然不存在(出现与 HTTP 404 错误相关的问题)。

配置如下:

<services>
   <service behaviorConfiguration="WebServiceName.ServiceBehavior1" name="WebServiceName.Service1">
    <endpoint address="" binding="wsHttpBinding" bindingConfiguration="Binding1"
     contract="WebServiceName.I_Service1" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
     <host>
       <baseAddresses>
         <add baseAddress="http://localhost/WebServiceName/Service1/Service.svc" />
       </baseAddresses>
     </host>
   </service>
   <service behaviorConfiguration="WebServiceName.ServiceBehavior2" name="WebServiceName.Service2">
    <endpoint address="" binding="wsHttpBinding" bindingConfiguration="Binding1"
     contract="WebServiceName.I_Service2" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
     <host>
       <baseAddresses>
         <add baseAddress="http://localhost/WebServiceName/Service2/Service.svc" />
       </baseAddresses>
     </host>
   </service>
  </services>

【问题讨论】:

【参考方案1】:

我一直这样做的方式如下:为服务设置一个“基地址”,并将端点地址指定为不同的文本以附加到该基地址...

 <service name="MyNamespace.MyService">
    <endpoint address="FirstEndpointAddress" binding="netTcpBinding"
      name="FirstEndpointName"
      contract="MyNamespace.FirstEndpointContract" />
    <endpoint address="SecondEndpointAddress" binding="netTcpBinding"
      name="SecondEndpointName"
      contract="MyNamespace.SecondEndpointContract" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:8733/MyBaseAddress" />
      </baseAddresses>
    </host>
  </service>

因此,在您的情况下,基地址可能是 localhost/WebServiceName,端点 1 的端点地址可能是 Service1/Service.svc。同样对于端点 2,它可能是 Service2/Service.svc。我可以看到您已按照建议将完整地址放入端点地址,但我只能说我已经成功地这样做了。

【讨论】:

即使使用这种方法,我也会收到 localhost:8733/MyBaseAddress/FirstEndpointName/Service.svc 的 HTTP 404 错误(尽管当我尝试在客户端中添加服务引用时显然是 localhost:8733/MyBaseAddress /Service.svc 在发现服务时出现,这两个接口在我的情况下都很糟糕)。是否存在 IIS 而不是 web.config 的配置错误?我尝试为两个端点生成两个虚拟目录,但两个虚拟目录都绑定到第一个端点的接口。 除非您为某个端点提供了地址“FirstEndpointName/Service.svc”,否则我不会期望您使用的地址能够正常工作。请记住端点名称和端点地址是不同的东西。 最终地址变为:localhost:8733/MyBaseAddress/Service.svc/FirstEndpointAddress 和 localhost:8733/MyBaseAddress/Service.svc/SecondEndpointAddress 在客户端代码中: var svcClient = new ServiceReference1.ServiceClient(" SecondEndpointName");【参考方案2】:

目前我对这个问题的解决方案是在我的 web 服务中合并两个 .svc 文件来分隔两个接口。 这样,我有 localhost/WebServiceName/Service1.svclocalhost/WebServiceName/Service2.svc

使用端点配置

<services>
   <service behaviorConfiguration="WebServiceName.ServiceBehavior1" name="WebServiceName.Service1">
    <endpoint address="" binding="wsHttpBinding" bindingConfiguration="Binding1"
     contract="WebServiceName.I_Service1" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
     <host>
       <baseAddresses>
         <add baseAddress="http://localhost/WebServiceName/Service1.svc" />
       </baseAddresses>
     </host>
   </service>
   <service behaviorConfiguration="WebServiceName.ServiceBehavior2" name="WebServiceName.Service2">
    <endpoint address="" binding="wsHttpBinding" bindingConfiguration="Binding2"
     contract="WebServiceName.I_Service2" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
     <host>
       <baseAddresses>
         <add baseAddress="http://localhost/WebServiceName/Service1.svc" />
       </baseAddresses>
     </host>
   </service>
  </services>

这个解决方案不一定是最好的(如果客户真的想要,它可以发现这个服务公开了 2 个不同的接口,但我可以用不同的凭据/令牌保护它们)。但目前我会接受它。

【讨论】:

【参考方案3】:

我试着做你描述的东西。这一切都成功了。如果某些步骤对您来说很明显,请不要生气。所以:

    创建 WCF 服务应用程序项目。 添加两个 WCF 服务项(默认为创建接口和 svc 文件)。 创建 Web 应用程序项目。 使用“发现”按钮添加两个服务引用(右键单击 Web 应用项目 ==> 添加服务引用)(应该可以看到两个 Web 服务)。 就是这样。

默认情况下,我在 Web 应用程序项目中得到以下 Web.config:

     <system.serviceModel>
<bindings>
  <basicHttpBinding>
    <binding name="BasicHttpBinding_IService1" closeTimeout="00:01:00"
      openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
      allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
      maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
      messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
      useDefaultWebProxy="true">
      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
      <security mode="None">
        <transport clientCredentialType="None" proxyCredentialType="None"
          realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
    </binding>
    <binding name="BasicHttpBinding_IService2" closeTimeout="00:01:00"
      openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
      allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
      maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
      messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
      useDefaultWebProxy="true">
      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
      <security mode="None">
        <transport clientCredentialType="None" proxyCredentialType="None"
          realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
    </binding>
  </basicHttpBinding>
</bindings>
<client>
  <endpoint address="http://localhost:3597/Service1.svc" binding="basicHttpBinding"
    bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
    name="BasicHttpBinding_IService1" />
  <endpoint address="http://localhost:3597/Service2.svc" binding="basicHttpBinding"
    bindingConfiguration="BasicHttpBinding_IService2" contract="ServiceReference2.IService2"
    name="BasicHttpBinding_IService2" />
</client>

您可以尝试重建 WCF 项目并更新 WebReferences。

【讨论】:

说明明显的步骤并没有错;大多数时候,它们是我们忘记的。尽管如此,我的问题是关于如何配置具有 2 个端点的单个 Web 服务,而不是两个不同的 Web 服务。此外,配置部分是关于应该在该 Web 服务 web.config 中配置的内容,而不是在引用它的应用程序的 web.config 或 app.config 中。

以上是关于WCF 服务在 2 个不同的服务合同上公开 2 个端点的主要内容,如果未能解决你的问题,请参考以下文章

WCF - 使用完全相同的数据合同的多个服务合同

一个 WCF 服务中的多个合同_但调用第二个合同时出错

WCF - 在合同列表中找不到合同名称

可移植/可互操作的 WCF 合同

大型 WCF 服务的最佳实践?

在具有 2 个不同 .SVC 文件的多线程环境中调用 WCF 服务。同时调用两个服务时出错