Сочетание SOAP / JSON / XML в WCF с использованием UriTemplate - PullRequest
25 голосов
/ 18 марта 2010

Я пытаюсь создать общий интерфейс веб-службы с использованием WCF, чтобы сторонние разработчики могли подключиться к нашему программному обеспечению. После долгих усилий и чтения ( этот вопрос очень помог), я наконец-то начал работать вместе с 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'.

Но, конечно, без использования <enableWebScript/>, JSON не работает.

Единственное, что я видел, что, как мне кажется, сработает, это создание 3 разных сервисов (файлов .svc), которые реализуют интерфейс, который определяет контракт, но в классах указывают разные атрибуты WebGet / WebInvoke для каждого класса. , Это кажется большой дополнительной работой, честно говоря, я не понимаю, почему фреймворк для меня не справляется Реализация всех классов будет одинаковой, за исключением атрибутов, что означает, что с течением времени ошибки / изменения могут быть легко исправлены / выполнены в одной реализации, но не в других, что приведет к противоречивому поведению при использовании JSON против Реализация SOAP, например.

Я что-то здесь не так делаю? Я использую совершенно неправильный подход и неправильно использую WCF? Есть лучший способ сделать это?

Имея опыт работы с веб-материалами, я думаю, что для некоторого фреймворка будет возможно справиться с этим ... У меня даже есть идея, как его построить. Просто кажется, что WCF должен это делать, и я не хочу изобретать велосипед.

Ответы [ 3 ]

27 голосов
/ 23 марта 2010

На самом деле <enableWebScript /> - это , а не , необходимое для "чистой" поддержки JSON. WebScriptEnablingBehavior требуется только в том случае, если вы хотите поддерживать ASP.NET AJAX. Чаще всего, если вы пытаетесь работать со стандартными библиотеками сценариев, вы не хотите включить эту поддержку для своих служб.

Вместо этого, что вы хотите сделать для вашей конечной точки JSON, просто используйте WebHttpBehavior и установите DefaultOutgoingResponseFormat = "JSON". Проблема заключается в том, что в .NET 3.5 вы не можете управлять этим параметром через config, поскольку WebHttpElement не предоставляет эти свойства для конфигурации. Чтобы обойти это, в 3.5 предоставлена ​​реализация того, что я называю EnhancedWebHttpElement здесь, в этом ответе , на другой вопрос StackOverflow.

К счастью, Microsoft осознала этот недостаток и включила настройку всех параметров WebHttpBehavior через WebHttpElement в 4.0 .

4 голосов
/ 14 февраля 2011

Ответ Дрю точен, но я думаю, что вопрос остается в силе. Есть ли разумный способ иметь JSON для AJAX () и благословения UriTemplate?

Я думаю, что стоит упомянуть, что возвращаемый JSON отличается от JSON, сгенерированного с помощью [WebGet (ResponseFormat = WebMessageFormat.Json)]. Первый из них обернут вокруг элемента MS AJAX 'd', например. { "D": [{...}]}.

0 голосов
/ 09 декабря 2013

Вы указали целочисленные параметры в вашей операции. Шаблон URI плохо работает с параметрами int. Пожалуйста, измените его на строку, это будет работать.

Я думаю, вам нужно написать свой собственный QuerystringConverter для использования int с URITemplate.

...