I am extending WebHttpBehavior
to expose a WCF REST service with customized serialization and deserialization (plus a certain number of other features that are not relevant to the problem).
The new behavior uses an implementation of IDispatchMessageFormatter
to perform custom serialization and deserialization of POCOs served by the service and sent to it thanks to the SerializeReply
and DeserializeRequest
methods.
I can serve XML and JSON exactly how I need them in SerializeReply
.
I can deserialize XML without a problem, however I can't seem to find the way to deserialize a JSON message because I can't obtain the plain text contained in the Message
parameter of DeserializeRequest
.
This is what the code in DeserializeRequest
looks like right now:
if (format == System.ServiceModel.Web.WebMessageFormat.Json)
{
var data = ""; // TODO obtain plain text from Message object
var json = JsonConvert.DeserializeObject(data, paramType, new IsoDateTimeConverter(), new StringEnumConverter());
parameters[paramIndex] = json;
}
else
{
var serializer = new System.Xml.Serialization.XmlSerializer(paramType, string.Empty);
var reader = message.GetReaderAtBodyContents();
parameters[paramIndex] = serializer.Deserialize(reader);
}
I'm using Json.NET for JSON (de)serialization.
Any suggestions on how to obtain plain text from the Message
object in order to deserialize it would be greatly appreciated.
If you think there's something wrong in my approach I'd also like to hear of it in the comments.
You need to make sure that the WebMessageFormat
of the Message is set to Raw, otherwise WCF will use a the JsonMessageEncoder
in order to create the Message
which in turn won't allow you to get to the raw message content.
You do that by implementing a custom WebContentTypeMapper
:
public class RawMapper : WebContentTypeMapper
{
public override WebContentFormat GetMessageFormatForContentType(string contentType)
{
return WebContentFormat.Raw;
}
}
...which needs to be applied to the WebHttpBinding:
webHttpBinding.ContentTypeMapper = new RawMapper();
..or via configuration:
<bindings>
<webHttpBinding>
<binding contentTypeMapper="Samples.RawMapper, MyContentTypeMapperAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</webHttpBinding>
</bindings>
With that in place, you can then retrieve the request body as a String like that:
public void DeserializeRequest(Message message, object[] parameters)
{
var bodyReader = message.GetReaderAtBodyContents();
bodyReader.ReadStartElement("Binary");
byte[] rawBody = bodyReader.ReadContentAsBase64();
string messageAsString;
using (var reader = new StreamReader(new MemoryStream(rawBody)))
messageAsString = reader.ReadToEnd();
object jsonObj = JsonConvert.DeserializeObject(messageAsString);
parameters[0] = jsonObj;
}