WCF - отправка JSON в конечную точку - как должно выглядеть тело контента запроса? - PullRequest
2 голосов
/ 19 октября 2011

Я только что потратил пару часов на отладку и просмотр таких вопросов, как POSTING JSON для конечной точки REST WCF и Общая десериализация WCSON JSON , но в настоящее время я думаю, что мой код и / или отладка не проходит на базовом уровне ...

Я настроил службу WCF, например:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, IncludeExceptionDetailInFaults = true)]
public class AutomationService : IAutomationService
{
    [WebInvoke(Method = "POST", UriTemplate = "getNextCommand")]
    public CommandBase GetNextCommand(int timeoutInMilliseconds)
    {
        // stuff
    }
}

, где IAutomationService:

[ServiceContract]
public interface IAutomationService
{
    [OperationContract]
    [ServiceKnownType("GetKnownTypes", typeof(KnownTypeProvider))]
    CommandBase GetNextCommand(int timeoutInMilliseconds);
}

и теперь я успешно настроил эту службу с конечными точками SOAP и JSON.

Однако ... Я не могу понять, как вызвать службу, используя переменные, переданные в ContentBody из Fiddler.

Например, я могу позвонить в службу с помощью POST на Uri - например,

   POST  http://localhost:8085/phoneAutomation/jsonAutomate/getNextCommand?timeoutInMilliseconds=10000

Однако, если я попытаюсь поместить содержимое в тело, я получу исключение. например, * 1 020 *

POST http://localhost:8085/phoneAutomation/jsonAutomate/getNextCommand
Host: localhost:8085
Connection: keep-alive
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.202 Safari/535.1
Accept: application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: Orchrd-=%7B%22Exp-N42-Settings%22%3A%22open%22%2C%22Exp-N42-New%22%3A%22open%22%7D
Content-Length: 31
Content-Type: application/json

{"timeoutInMilliseconds":10000}

завершается с:

Сервер обнаружил ошибку при обработке запроса. Исключение сообщение «Произошла ошибка при десериализации объекта типа System.Int32. Значение '' не может быть проанализировано как тип 'Int32'. '. Увидеть логи сервера для более подробной информации. Трассировка стека исключений:

в System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions (XmlReaderDelegator читатель, логическое verifyObjectName, DataContractResolver dataContractResolver) в System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject (XmlDictionaryReader читатель, Boolean verifyObjectName) в

...

У кого-нибудь есть идеи, что я делаю неправильно (кроме использования WCF!) - я просто не уверен, какой должна быть форма JSON {"timeoutInMilliseconds": 10000}.

1 Ответ

1 голос
/ 19 октября 2011

По умолчанию "body style" службы WCF REST имеет значение "Bare", что означает, что для операций с одним входом значение операции должно идти "как есть", без каких-либо объектов, обертывающих ее.Это означает, что в вашем случае это будет работать:

POST http://localhost:8085/phoneAutomation/jsonAutomate/getNextCommand
Host: localhost:8085
Connection: keep-alive
Cache-Control: max-age=0
...
Content-Length: 5
Content-Type: application/json

10000

Еще одна вещь, не имеющая прямого отношения к вашему вопросу: если вы определяете сервисный контракт в интерфейсе, вы должны также добавить любые "связанные с контрактом"атрибуты (такие как WebInvoke) также в интерфейсе.Это сделает ваш код похожим на это:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, IncludeExceptionDetailInFaults = true)]
public class AutomationService : IAutomationService
{
    public CommandBase GetNextCommand(int timeoutInMilliseconds)
    {
        // stuff
    }
}

[ServiceContract]
public interface IAutomationService
{
    [OperationContract]
    [ServiceKnownType("GetKnownTypes", typeof(KnownTypeProvider))]
    [WebInvoke(Method = "POST", UriTemplate = "getNextCommand")]
    CommandBase GetNextCommand(int timeoutInMilliseconds);
}

И еще одна информация: если вы хотите отправить запрос так же, как вы изначально ({"tiemoutInMilliseconds":10000}), вы можете установить свойство BodyStyleв атрибуте [WebInvoke] для Wrapped (или WrappedRequest):

[ServiceContract]
public interface IAutomationService
{
    [OperationContract]
    [ServiceKnownType("GetKnownTypes", typeof(KnownTypeProvider))]
    [WebInvoke(Method = "POST",
               UriTemplate = "getNextCommand",
               BodyStyle = WebMessageBodyStyle.WrappedRequest)]
    CommandBase GetNextCommand(int timeoutInMilliseconds);
}
...