Mixing XML and JSON in RESTful WCF without separate methods

I have a RESTful WCF service that can return XML, JSON or JSONP, depending on the arguments, for example. /service.svc/stuff?format=xml or service.svc/stuff?format=json&callback=myCallback . To do this, I created a custom Behavior, MethodEncoder, and MethodEncoderFactory that handle the JSONP callback and select the author based on the format argument. In my encoder WriteMessage() method, I am doing something like

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

Then I define my maintenance methods as if they just return JSON, but use my own binding element:

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

And it almost works. When I ask for XML or JSON, I get something in the correct format, but the XML does not serialize as I expect. Here's what the XML looks like:

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

While if I just installed WebMessageFormat in XML, I would get something like the following:

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

I definitely want the latter. I suppose this happens because the result is serialized in the dictionary when creating the Message object; my custom encoder just decides how to write this dictionary to the response stream. Thus, he gets the right encoding, but not exactly the format that has already been resolved using ResponseFormat.

First of all, is it? If so, how can I fix this? For example, can I write my own WebMessageFormat? Or do I just need to give and write separate methods (and URI patterns) that have different ResponseFormat properties for / json / * and / xml / *?

Update: In .net 4 there is the WebOperationContext.Current.OutgoingResponse.Format property, which you can simply set. I assume my problem boils down to: is there a way to do this in .net 3.5?

+4
source share
1 answer

Yes, there is a way to accomplish what you want in .NET 3.5, without writing separate methods.

This blog post describes the situation you are describing: changing the type of response content based on an incoming request. But the message describes a slightly different approach to the solution.

In particular, the requestor indicates the desired NOT content type in the request URL, but rather in the Accept request header.

The solution involves using a custom WebHttpBehavior that checks the Accept header and formats the response accordingly. In my opinion, a very elegant solution. You have nothing to do in your business logic to get responsive formatting. Just attach the behavior and it works.


Also check out the WCF REST Contrib library on CodePlex.

+2
source

Source: https://habr.com/ru/post/1299375/


All Articles