2010-03-18 3 views
25

Я пытаюсь создать общий интерфейс веб-сервиса с использованием WCF, чтобы позволить сторонним разработчикам подключаться к нашему программному обеспечению. После долгих битв и чтения (this question помогло много), я наконец получил SOAP, JSON и XML (POX), работая вместе.Комбинированный SOAP/JSON/XML в WCF с использованием UriTemplate

Чтобы упростить, вот мой код (чтобы сделать этот пример просто, я не использую интерфейсы - я попробовать это в обоих направлениях):

<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 должен это делать, и я действительно не хочу изобретать велосипед.

+0

Ваш пример кода здесь был очень полезным! У меня были только привязки JSON и я обнаружил, что не могу использовать сервисы из приложения .net, так что это именно то, что я был после! :) – Shawson

+0

Обратите внимание, что я считаю это полностью устаревшим теперь с [ASP.NET Web API] (http://www.asp.net/web-api); код, вызвавший задание этого вопроса, давно переписан с использованием Web API. Я бы очень рекомендовал против использования WCF для хорошо, ничего, если вы [застряли в темные века и действительно нуждаетесь в SOAP] (http://stackoverflow.com/questions/11317572/asp-net-webapi-soap). – gregmac

ответ

27

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

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

К счастью, Microsoft осознала этот недостаток и включила конфигурацию всех настроек WebHttpBehavior через WebHttpElement in 4.0.

4

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

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

0

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

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