Подтвердить что ты не робот

Комбинированный SOAP/JSON/XML в WCF, используя UriTemplate

Я пытаюсь создать общий интерфейс веб-сервиса с помощью 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 не работает.

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

Ответ 3

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

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