У меня есть служба 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?