0

我有一个 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()}

我会感谢一些关于我做错了什么的指导。

谢谢

4

2 回答 2

4

At a glance, it appears that you've mixed up client endpoints with service endpoints in your service's config file. There's no reason for client endpoints to appear in the service's config file, unless that service is itself calling another service.

Your WinForm's config file is defining a client with basicHttpBinding, but you do not expose a service endpoint with BasicHttpBinding, which is most likely the reason for the error you're getting.

I would try deleting the client endpoints in your service's config file, and add them to the <services> section, like this:

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

Remember the ABC's of WCF: A = Address, B = Binding and C = Contract - those three items define a service.

Since you added a client that needed a different binding then your test harness or your ASP.NET application, you need to expose a second endpoint with that binding.

EDITED

As @marc_s pointed out, you'll need two distinct relative addresses. I've updated the config file to reflect that.

I've not had an occasion to use multiple endpoints myself, but I believe you'd use them this way, with the base address being provided by the location of the *.svc file:

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

With the first being for the BasicHttpBinding and the second being for the WebHttpBinding.

于 2013-08-24T06:17:29.393 回答
3

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

服务的“基”地址由 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

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

于 2013-08-24T07:42:22.260 回答