【问题标题】:WCF Endpoint. Multiple ClientsWCF 端点。多个客户
【发布时间】:2013-08-24 15:42:22
【问题描述】:

我有一个 IIS 托管的 WCF 网络服务。它从两个消费者开始。

1) 同一解决方案中的 WinForm 测试工具,用于在 IDE 中测试 WCF 合同。

2) 使用已发布版本的 Asp.Net Web 应用程序。

可以说,一切都是开箱即用的。

随之而来的是第三个消费者,一款 Android 应用。要正确使用此功能,必须使用 JSON WebGets 和 Webinvokes 装饰 WCF 合同,并更改 WCF Web.config 以适应。

现在原来的两个消费者不再工作了。所以我需要更改 Web.config 和/或 App.configs 以获得所有三个都可以工作的配置。

首先关注 IDE。我有 WCF 服务 Web.Config 的以下服务模型部分。

<system.serviceModel>
  <client>
    <endpoint binding="webHttpBinding" bindingConfiguration="JsonBinding"
              contract="CouponParkingWCF.ICouponService" name="Json" 
              kind="" endpointConfiguration="">
      <identity>
        <certificateReference storeName="My" storeLocation="LocalMachine"
                              x509FindType="FindBySubjectDistinguishedName" />
      </identity>
    </endpoint>
    <endpoint address="http://localhost:8707/CouponParking.svc"
              binding="basicHttpBinding" contract="CouponParkingWCF.ICouponService"
              name="BasicHttpBinding_ICouponService" />
  </client>
  <bindings>
    <basicHttpBinding>
      <binding name="basicHttp" />
    </basicHttpBinding>
    <webHttpBinding>
      <binding name="JsonBinding" />
    </webHttpBinding>
  </bindings>
  <services>
    <service name="CouponParkingWCF.CouponService">
      <endpoint behaviorConfiguration="JsonBehavior" binding="webHttpBinding"
                bindingConfiguration="" name="jsonEndPoint"
                contract="CouponParkingWCF.ICouponService" />
    </service>
  </services>
  <behaviors>
    <endpointBehaviors>
      <behavior name="JsonBehavior">
        <webHttp />
      </behavior>
    </endpointBehaviors>
    <serviceBehaviors>
      <behavior name="">
        <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="true" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <protocolMapping>
    <add binding="basicHttpsBinding" scheme="https" />
  </protocolMapping>    
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
                             multipleSiteBindingsEnabled="false" />
</system.serviceModel>

WinForm 测试工具 App.config 具有:

<system.serviceModel>
  <bindings>
    <basicHttpBinding>
      <binding name="BasicHttp" />
    </basicHttpBinding>
  </bindings>
  <client>
    <endpoint address="http://localhost:8707/CouponParking.svc"
              binding="basicHttpBinding"
              bindingConfiguration="BasicHttp" 
              contract="CouponParking.ICouponService"
              name="BasicHttpBinding_ICouponService" />
  </client>
</system.serviceModel>

我在配置端点方面没有经验,以上都是基于示例和猜测。

当我运行测试工具时,wcf 客户端会实例化,但对合约的调用失败:

There was no endpoint listening at http://localhost:8707/CouponParking.svc 
that could accept the message. This is often caused by an incorrect address
or SOAP action. See InnerException, if present, for more details."

内部异常是:

{"The remote server returned an error: (404) Not Found."}
[System.Net.WebException]: {"The remote server returned an error: (404) Not Found."}
Data: {System.Collections.ListDictionaryInternal}
HelpLink: null
HResult: -2146233079
InnerException: null
Message: "The remote server returned an error: (404) Not Found."
Source: "System"
StackTrace: "   at System.Net.HttpWebRequest.GetResponse()\r\n   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)"
TargetSite: {System.Net.WebResponse GetResponse()}

如果我做错了什么,我将不胜感激。

谢谢

【问题讨论】:

  • 您是否尝试在同一端点上向不同的客户端(具有不同的需求 - 即绑定)公开相同的服务?如果是这样,你不能那样做。您需要为服务的不同实现公开不同的端点。
  • 另外,您能否将配置文件发布为在添加第三个客户端之前?了解它在工作时的状态以及现在的状态(当它不工作时)可能会有所帮助。
  • 每个服务器端端点都有定义一个绑定 - 例如您不能拥有一个端点,既支持您的第一个和第二个客户端的 basicHttpBinding (SOAP),同时还支持 Android 客户端的 webHttpBinding (REST)。为此,您需要使用两个单独的端点

标签: c# wcf web-services


【解决方案1】:

乍一看,您似乎在服务的配置文件中混淆了客户端端点和服务端点。客户端端点没有理由出现在服务的配置文件中,除非该服务本身正在调用另一个服务。

您的 WinForm 配置文件使用 basicHttpBinding 定义客户端,但您没有使用 BasicHttpBinding 公开 service 端点,这很可能是您遇到错误的原因。

我会尝试删除服务配置文件中的客户端端点,并将它们添加到 &lt;services&gt; 部分,如下所示:

<system.serviceModel>
  <bindings>
    <basicHttpBinding>
      <binding name="basicHttp" />
    </basicHttpBinding>
    <webHttpBinding>
      <binding name="JsonBinding" />
    </webHttpBinding>
  </bindings>
  <services>
    <service name="CouponParkingWCF.CouponService">
      <endpoint address="SOAP"
                binding="basicHttpBinding" 
                contract="CouponParkingWCF.ICouponService"
                name="BasicHttpBinding_ICouponService" />
      <endpoint address="JSON"
                binding="webHttpBinding" bindingConfiguration="JsonBinding"
                contract="CouponParkingWCF.ICouponService" name="Json" 
                kind="" endpointConfiguration="">
        <identity>
          <certificateReference storeName="My" storeLocation="LocalMachine"
                                x509FindType="FindBySubjectDistinguishedName" />
        </identity>
      </endpoint>
    </service>
  </services>

记住 WCF 的 ABC:A = 地址,B = 绑定和 C = 合同 - 这三个项目定义了一个服务。

由于您添加的客户端需要与您的测试工具或 ASP.NET 应用程序不同的绑定,因此您需要使用该绑定公开第二个端点。

已编辑

正如@marc_s 所指出的,您需要两个不同的相对地址。我已经更新了配置文件以反映这一点。

我自己没有机会使用多个端点,但我相信您会以这种方式使用它们,基地址由 *.svc 文件的位置提供:

http://localhost:8707/CouponParking.svc/SOAP
http://localhost:8707/CouponParking.svc/JSON

第一个用于BasicHttpBinding,第二个用于WebHttpBinding

【讨论】:

  • 您必须为您定义的这两个端点提供两个不同的地址。它们的“基”地址由 IIS 虚拟目录和 *.svc 文件的位置定义 - 现在您需要两个不同的相对地址来区分这两个端点......
  • @marc_s - 谢谢。我已经更新了我的答案,以反映我对你所说的话的理解。如果仍然有错误,请告诉我。
  • 感谢 Tim,您和 marc_s 不仅提供了解决方案,还提供了清晰的解释。您的答案在 marc_s 之前,所以我已将您标记为答案。
【解决方案2】:

您基本上只需要两个单独的端点来为您的 Android 客户端(REST 绑定)提供basicHttpBinding(SOAP 绑定)和webHttpBinding

服务的“基”地址由 IIS 虚拟目录和*.svc 文件所在的位置(http://localhost:8707/CouponParking.svc)定义 - 因此这两个服务都可以在此“基”地址加上定义的任何相对地址访问

所以你需要这样配置:

<services>
   <service name="CouponParkingWCF.CouponService">
      <!-- define the basicHttp (SOAP) endpoint at the base address -->
      <endpoint name="SoapEndpoint"
          address=""
          binding="basicHttpBinding" 
          contract="CouponParkingWCF.ICouponService" />
      <!-- define the REST endpoint at (base)+"/rest" -->
      <endpoint name="RestEndpoint"
          address="rest"
          behaviorConfiguration="JsonBehavior" 
          binding="webHttpBinding" 
          contract="CouponParkingWCF.ICouponService" />
   </service>
</services>

使用此设置,您应该能够使用basicHttpBinding (SOAP) 调用您的服务

http://yourServer:8707/CouponParking.svc

您应该能够访问基于 REST、启用 JSON 的端点

http://yourServer:8707/CouponParking.svc/rest

两个服务器端端点将由相同的服务代码处理 - 只是端点(以及端点理解的协议)不同

【讨论】:

  • 你和蒂姆都是对的。我已将蒂姆的答案标记为他的第一个答案。我不仅感谢解决方案,还感谢您的解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多