Смешивание XML и JSON в RESTful WCF без отдельных методов - PullRequest
4 голосов
/ 26 января 2010

У меня есть служба RESTful WCF, которая может возвращать XML, JSON или JSONP, в зависимости от аргументов, например, /service.svc/stuff?format=xml или service.svc/stuff?format=json&callback=myCallback. Чтобы сделать это, я создал пользовательские Behavior, MethodEncoder и MethodEncoderFactory, которые обрабатывают обертку обратного вызова JSONP и выбирают программу записи на основе аргумента формата. В методе WriteMessage() моего кодировщика я делаю что-то вроде

XmlWriter writer = IsXmlRequested() ? XmlDictionaryWriter.CreateTextWriter(stream) :
  JsonReaderWriterFactory.CreateJsonWriter(stream)
message.WriteMessage(writer);

Затем я определяю свои сервисные методы, как будто они просто возвращают JSON, но используют мой пользовательский элемент привязки:

[OperationContract, JSONPBehavior, WebGet(ResponseFormat = WebMessageFormat.Json,
  UriTemplate = "stuff")
public List<Thing> GetStuff(){...}

И это почти работает. Когда я спрашиваю XML или JSON, я получаю что-то в правильном формате, но XML не сериализуется, как я ожидаю. Вот как выглядит XML:

<root type="array">
 <item type="object">
  <FirstPropertyOnAThing>1</FirstPropertyOnAThing>

Тогда как, если бы я просто установил WebMessageFormat в XML, я бы получил что-то вроде этого:

<ArrayOfThings xmlns="...>
 <Thing ...>
  <FirstPropertyOnAThing>1</FirstPropertyOnAThing>

Я определенно хочу последнее. Я предполагаю, что это происходит, потому что результат сериализуется в словарь при создании объекта Message; Мой пользовательский кодер просто решает, как записать этот словарь в поток ответов. Таким образом, он получает правильное кодирование, но не точно формат, который уже был определен в ResponseFormat.

Во-первых, это правильно? Если так, как я могу это исправить? Например, могу ли я написать свой собственный WebMessageFormat? Или мне просто нужно отдать и написать отдельные методы (и шаблоны URI), которые имеют разные свойства ResponseFormat для / json / * и / xml / *?

Обновление: В .net 4 есть свойство WebOperationContext.Current.OutgoingResponse.Format, которое вы можете просто установить. Я думаю, что моя проблема сводится к: есть ли способ сделать это в .net 3.5?

1 Ответ

2 голосов
/ 30 января 2010

Да, в .NET 3.5 есть способ выполнить то, что вы хотите, без написания отдельных методов.

В этом сообщении в блоге рассматривается ситуация, которую вы описываете: изменение типа содержимого ответа на основе входящего запроса. Но пост описывает немного другой подход к решению.

В частности, запрашивающая сторона указывает желаемый тип содержимого НЕ в URL-адресе запроса, а в заголовке Accept запроса.

Решение включает использование пользовательского WebHttpBehavior , который проверяет заголовок Accept и соответствующим образом форматирует ответ. Очень элегантное решение, на мой взгляд. Вам ничего не нужно делать в своей бизнес-логике, чтобы получить адаптивное форматирование. Просто прикрепите поведение, и оно работает.


Также ознакомьтесь с библиотекой WCF REST Contrib в CodePlex.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...