I've seen quite a few times in the forums people asking how to control exactly how the data returned by a WCF service. People want to use a certain format for the output of the data which isn't (natively) supported by WCF, such as XML or JSON. A few examples of questions of this nature:
One way to do it is to create a separate MessageEncoder, which is capable of taking a Message object and converting it to the bytes, and use that encoder in the binding of the endpoint which contains the operation. Although this is certainly doable, it requires a lot of work - a Message object contains an XML representation of its contents, so you'd need a mapping between XML and whichever format you want, possibly requiring a new XmlWriter/XmlReader implementation; you'll also need all the plumbing parts needed to connect the encoder with the endpoint (a MessageEncoderFactory, a MessageEncodingBindingElement and so on).
The Web programming model introduced in WCF on .NET Framework 3.5 simplifies this task. The magic happens when the operation return type is of System.IO.Stream (the abstract class, not one of its concrete implementations). By returning a stream, WCF assumes that the operation wants total control over the bytes that will be returned in the response, and will apply no formatting whatsoever in the data that is returned. This service, for example, solves the first question listed above:
[
This should work in most of the cases, since the result is fairly simple. It is a good practice, however, whenever you're using the raw programming model, to specify the Content-Type for the response. If nothing is specified, responses of operations with Stream return values will have a content type of application/octet-stream (i.e., binary). Some browsers (such as IE) may identify that the content is actually text, and print it correctly, but that's not a guarantee. The example will then become:
[ServiceContract]public class RawService{ [OperationContract, WebGet] public System.IO.Stream GetValue() { string result = "Hello world"; byte[] resultBytes = Encoding.UTF8.GetBytes(result); WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain"; return new MemoryStream(resultBytes); }}
Notice that this isn't limited to text only; with the raw programming model you can create a service which returns pretty much anything, in any format, such as images created on the fly: