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<string> phoneNumbers
。默认情况下,WebInvoke 是 GET
,但不能从 URL 反序列化 List<string>
。我认为如果您将其更改为 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:IService1 和 IService2。
要运行 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 方法不允许