使用 UriTemplate 在 WCF 中组合 SOAP/JSON/XML

Posted

技术标签:

【中文标题】使用 UriTemplate 在 WCF 中组合 SOAP/JSON/XML【英文标题】:Combined SOAP/JSON/XML in WCF, using UriTemplate 【发布时间】:2011-01-29 02:32:14 【问题描述】:

我正在尝试使用 WCF 构建通用 Web 服务接口,以允许第 3 方开发人员连接到我们的软件。经过一番努力和阅读(this question 帮助很大),我终于让 SOAP、JSON 和 XML (POX) 一起工作。

为了简化,这是我的代码(为了让这个例子简单,我没有使用接口——我确实尝试过这两种方式):

<ServiceContract()> _
Public Class TestService
    Public Sub New()
    End Sub

    <OperationContract()> _
    <WebGet()> _
    Public Function GetDate() As DateTime
        Return Now
    End Function


    '<WebGet(UriTemplate:="getdateoffset/numDays")> _
    <OperationContract()> _
    Public Function GetDateOffset(ByVal numDays As Integer) As DateTime
        Return Now.AddDays(numDays)
    End Function

End Class

和 web.config 代码:

<services>
  <service name="TestService" 
           behaviorConfiguration="TestServiceBehavior">
    <endpoint address="soap" binding="basicHttpBinding" contract="TestService"/>
    <endpoint address="json" binding="webHttpBinding" behaviorConfiguration="jsonBehavior" contract="TestService"/>
    <endpoint address="xml" binding="webHttpBinding" behaviorConfiguration="poxBehavior" contract="TestService"/>
    <endpoint address="mex" contract="IMetadataExchange" binding="mexHttpBinding" />
  </service>
</services>
<behaviors>
  <endpointBehaviors>
    <behavior name="jsonBehavior">
      <enableWebScript/>
    </behavior>
    <behavior name="poxBehavior">
      <webHttp />
    </behavior>
  </endpointBehaviors>
  <serviceBehaviors>
    <behavior name="TestServiceBehavior">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>
  </serviceBehaviors>
</behaviors>

这确实有效 - 我可以转到 TestService.svc/xml/GetDate 获取 xml,TestService.svc/json/GetDate 获取 json,并将 SOAP 客户端指向 TestService.svc?wsdl 并让 SOAP 查询正常工作。

我要修复的部分是查询。我必须使用TestService.svc/xml/GetDateOffset?numDays=4 而不是TestService.svc/xml/GetDateOffset/4。如果我指定 UriTemplate,我会收到错误:

Endpoints using 'UriTemplate' cannot be used with 'System.ServiceModel.Description.WebScriptEnablingBehavior'.

当然,如果不使用&lt;enableWebScript/&gt;,JSON 就不起作用。

我认为唯一可行的另一件事是制作 3 个不同的服务(.svc 文件),它们都实现了一个指定合同的接口,但在类中为每个类指定不同的 WebGet/WebInvoke 属性.这似乎是很多额外的工作,坦率地说,我不明白为什么框架不能为我处理。除了属性之外,类的实现都是相同的,这意味着随着时间的推移,错误/更改很容易在一个实现中得到修复/完成,而在其他实现中则不然,导致使用 JSON vs 时的行为不一致例如 SOAP 实现。

我在这里做错了吗?我是否采取了完全错误的方法并滥用了 WCF?有一个更好的方法吗?

以我在网络方面的经验,我认为某种 类的框架应该可以处理这个问题......我什至对如何构建它有了一个想法。看起来 WCF 应该这样做,我真的不想重新发明***。

【问题讨论】:

您的代码示例非常有帮助!我只有 JSON 绑定,发现我无法使用 .net 应用程序中的服务,所以这正是我所追求的! :) 请注意,我认为现在 ASP.NET Web API 已经完全过时了;导致这个问题被问到的代码早就用 Web API 重写了。我强烈建议不要使用 WCF,除非你是 stuck in the dark ages and really need SOAP。 【参考方案1】:

实际上,&lt;enableWebScript /&gt; 不是“纯”JSON 支持所必需的。仅当您想要支持 ASP.NET AJAX 时才需要 WebScriptEnablingBehavior。通常,如果您尝试使用标准脚本库,您希望为您的服务启用此支持。

您想要为 JSON 端点做的只是使用 WebHttpBehavior 并设置 DefaultOutgoingResponseFormat="JSON"。问题是,在 .NET 3.5 中,您无法通过 config 控制此设置,因为 WebHttpElement 不会公开这些属性以进行配置。为了在 3.5 中解决这个问题,我为另一个 *** 问题提供了我称之为 EnhancedWebHttpElement here in this answer 的实现。

幸运的是,Microsoft 意识到了这个缺点,并通过WebHttpElement in 4.0 启用了所有WebHttpBehavior 设置的配置。

【讨论】:

【参考方案2】:

Drew 的回答是正确的,但我认为问题仍然存在。有没有一种理智的方式来为 AJAX () 提供 JSON 和 UriTemplate 的祝福?

我认为值得一提的是,返回的 JSON 与使用 [WebGet(ResponseFormat=WebMessageFormat.Json)] 生成的 JSON 不同。前者包裹在 MS AJAX 'd' 元素上,例如"d":[...]。

【讨论】:

【参考方案3】:

您在操作中指定了整数参数。 URI 模板不适用于 int 参数。请把它改成字符串,它会工作。

我认为您必须编写自己的 QuerystringConverter 才能将 int 与 URITemplate 一起使用。

【讨论】:

以上是关于使用 UriTemplate 在 WCF 中组合 SOAP/JSON/XML的主要内容,如果未能解决你的问题,请参考以下文章

WCF中UriTemplate中的可选参数

WCF REST模式下的UriTemplate路径问题

WCF中URITemplate中的可选查询字符串参数?

WCF 的复杂 UriTemplate

一个关于WCF调用远程链接返回405错误不允许使用此方法的问题

在 Postman 中使用路径参数测试 WCF API