WCF REST 方法和非 REST 方法

Posted

技术标签:

【中文标题】WCF REST 方法和非 REST 方法【英文标题】:WCF REST method and non-REST method 【发布时间】:2014-03-07 08:24:39 【问题描述】:

我有一个 WCF 服务,我需要一种方法接受 HTTP POST 请求,而另一种方法必须是非 REST。考虑下面的代码:

        [OperationContract]
        long[] Send(string body, List<string> phoneNumbers);


        [OperationContract]
        [WebInvoke(Method="POST", BodyStyle = WebMessageBodyStyle.WrappedRequest)]
        long[] SendByPost(string body, string phoneNumbers);

但我不知道为什么会出现以下错误:

合约“IService”的“发送”操作指定多个请求 无需任何包装元素即可序列化的主体参数。最多 一个主体参数可以在没有包装元素的情况下进行序列化。任何一个 删除额外的 body 参数或设置 BodyStyle 属性 WebGetAttribute/WebInvokeAttribute 到 Wrapped。

我该如何解决这个问题?

【问题讨论】:

我认为问题出在List&lt;string&gt; phoneNumbers。默认情况下,WebInvoke 是 GET,但不能从 URL 反序列化 List&lt;string&gt;。我认为如果您将其更改为 string[] phoneNumbers 应该可以工作。 我的问题是我不希望 URL 中的 Send 方法可用,只有第二种方法必须启用 REST! 然后删除OperationContract属性。 @wdosanjos 他无法删除 OperationContract 【参考方案1】:

首先,要在一个url中发送多个参数,可以使用GET方法代替POST

[OperationContract]
[WebInvoke(Method="POST", BodyStyle = WebMessageBodyStyle.WrappedRequest)]
long[] SendByGet(string body, string phoneNumbers);

要么改成这样:

[OperationContract]
[WebGet(UriTemplate = "/body=body?phoneNumbers=phoneNumbers"]
long[] SendByPost(string body, string phoneNumbers);

或者,如果您想使用 POST

[OperationContract]
[WebInvoke(Method="POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, 
UriTemplate = "MyUrl", RequestFormat = WebMessageFormat.Json
, ResponseFormat = WebMessageFormat.Json)]
long[] SendByPost(Info info);

这是你的 Info 类:

[DataContract]
Class Info

   [DataMember]
   public string Body get; set;

   [DataMember]
   public string PhoneNumbersget; set;

【讨论】:

他使用的 HTTP 方法无关紧要。【参考方案2】:

你有两个方法,你想把其中一个暴露给 REST,另一个暴露给另一个绑定,对吧?

为此,您需要为您的 wcf 服务 ([ServiceContract]) 创建多个接口。

以这个 Web.config 为例:

  <system.serviceModel>
<protocolMapping>
    <add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>    
<serviceHostingEnvironment minFreeMemoryPercentageToActivateService="1" aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
<bindings>
  <webHttpBinding>
    <binding name="RestBinding" maxBufferSize="1048576" maxReceivedMessageSize="1048576" maxBufferPoolSize="1048576">
      <readerQuotas maxDepth="2147483647" maxStringContentLength="1048576" maxArrayLength="1048576" maxBytesPerRead="1048576" maxNameTableCharCount="1048576"/>
    </binding>
  </webHttpBinding>
  <basicHttpBinding>
    <binding name="SoapBinding" maxReceivedMessageSize="20000000" messageEncoding="Text" maxBufferSize="20000000" maxBufferPoolSize="20000000" closeTimeout="00:10:00" openTimeout="00:10:00" sendTimeout="00:10:00"/>
  </basicHttpBinding>
  <wsHttpBinding>
    <binding name="SecureHttpBinding" messageEncoding="Mtom" closeTimeout="00:10:00" openTimeout="00:10:00" sendTimeout="00:10:00" maxBufferPoolSize="20000000" maxReceivedMessageSize="20000000">
      <readerQuotas maxDepth="32" maxStringContentLength="20000000" maxArrayLength="20000000"/>
      <security mode="None">
        <transport clientCredentialType="Windows"/>
      </security>
    </binding>
  </wsHttpBinding>
  <customBinding>
    <binding name="RawReceiveCapable">
      <webMessageEncoding webContentTypeMapperType="WCFService.RawContentTypeMapper, WCFService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      <httpTransport manualAddressing="true" maxReceivedMessageSize="524288000" transferMode="Buffered" /><!--transferMode="Streamed"-->
    </binding>
  </customBinding>
</bindings>
<services>
  <service name="WCFService.Service" behaviorConfiguration="WCFService.ServiceBehavior">
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:5000"/>
      </baseAddresses>
    </host>
    <!-- Service Endpoints -->
    <!-- Unless fully qualified, address is relative to base address supplied above -->
    <endpoint address="SOAP" binding="basicHttpBinding" bindingConfiguration="SoapBinding" contract="WCFService.IService1" name="SOAP_XML"/>
    <endpoint address="" binding="webHttpBinding" bindingConfiguration="RestBinding" contract="WCFService.IService2" behaviorConfiguration="EndpointJSONBehavior"/>
    <endpoint address="MTOM" binding="wsHttpBinding" bindingConfiguration="SecureHttpBinding" contract="WCFService.IService1" name="SOAP_MTOM"/>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior name="WCFService.ServiceBehavior">
      <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
      <serviceMetadata httpGetEnabled="true"/>
      <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
      <serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>
    </behavior>
  </serviceBehaviors>
  <endpointBehaviors>
    <behavior name="EndpointXMLBehavior">
      <webHttp defaultBodyStyle="Wrapped" defaultOutgoingResponseFormat="Xml"/>
    </behavior>
    <behavior name="EndpointJSONBehavior">
      <webHttp defaultBodyStyle="Wrapped" defaultOutgoingResponseFormat="Json"/>
    </behavior>
    <behavior name="EndpointRawBehavior">
      <webHttp/>
    </behavior>
  </endpointBehaviors>
</behaviors>

您可以在此处看到两个 ServiceContract:IService1IService2

要运行 IService1 中定义的方法,您需要使用soap封装。 IService2 公开的方法可以在没有肥皂的情况下以 REST 方式轻松调用 封装。

要使您的 SendByPost() 方法成为 RESTful 方法,您需要将其放在 IService2 中,并将其他方法放在不同的 ServiceContract(如 IService1)中。

【讨论】:

以上是关于WCF REST 方法和非 REST 方法的主要内容,如果未能解决你的问题,请参考以下文章

在 WCF REST 服务 POST 方法中处理 Json 请求数据

保护 WebServer 和 ApplicationServer 之间的内部 WCF 4.0 REST 服务的最简单方法是啥?

使用 jquery 查询 wcf rest 服务(不允许 405 方法)

自托管 WCF REST 服务 JSON POST 方法不允许

将 JSON 数据从 JQuery 发送到 WCF REST 方法时出现问题

wcf REST 服务和 JQuery Ajax Post:方法不允许