Question

I'm using RestSharp, and using Json.NET for serialization (see here).

Json.NET supports BSON, and since some of my requests have huge blocks of binary data, I think this would speed up my application dramatically. However, as far as I can tell, RestSharp does not seem to have any in-built support for BSON.

The use of Json.NET is implemented as a custom serializer for RestSharp, and so at first glance it looks like it would be possible to modify that custom serializer to use BSON. But, the Serialize method of the RestSharp.Serializers.ISerializer interface returns a string - which is (I assume) unsuitable for BSON. So, I assume that it would take some more significant changes to RestSharp to implement this change.

Has anyone figured out a way to do this?


Update: I looked at the RestSharp source, and discovered that the RestRequest.AddBody method that takes my object and serializes it into the request body eventually calls Request.AddParameter (with the serialized object data, and the parameter type RequestBody).

I figured that I might be able to serialize my object to BSON and then call Request.AddParameter directly - and indeed I can. However, when RestSharp then executes the RestRequest, it fails to put the binary content into the request, because there are other embedded assumptions about the request content being UTF-8 encoded.

Thus it looks like this hack would not work - there would need to be some changes made to RestSharp itself, and I'm not the man for the job...


Update 2: I decided to have a go at using the debugger to figure out how much of RestSharp I'd have to change to overcome the body-encoding issue, so I swapped out my NuGet version of RestSharp and included the RestSharp project in my solution. And... it worked.

It turns out that there has been a change to RestSharp in the last few months that isn't yet in the NuGet version.

So, you can now use AddParameter and pass in an already-BSON-encoded object, and RestSharp will send it off to the server without complaint.

Was it helpful?

Solution

Per the updates in my question, it turns out that if you have the latest RestSharp source, then instead of this:

        request.AddBody(myObject);

... you can do this instead whenever you have a payload that would benefit from using BSON:

        using (var memoryStream = new System.IO.MemoryStream())
        {
            using (var bsonWriter = new Newtonsoft.Json.Bson.BsonWriter(memoryStream))
            {
                var serializer = new Newtonsoft.Json.JsonSerializer();

                serializer.Serialize(bsonWriter, myObject);

                var bytes = memoryStream.ToArray();

                request.AddParameter("application/bson", bytes, RestSharp.ParameterType.RequestBody);
            }
        }

Note that the first parameter to AddParameter is supposedly the parameter name, but in the case of ParameterType.RequestBody it's actually used as the content type. (Yuk).

Note that this relies on a change made to RestSharp on April 11 2013 by ewanmellor/ayoung, and this change is not in the current version on NuGet (104.1). Hence this will only work if you include the current RestSharp source in your project.

OTHER TIPS

Gary's answer to his own question was incredibly useful for serializing restful calls. I wanted to answer how to deserialize restful calls using JSON.NET. I am using RestSharp version 104.4 for Silverlight. My server is using Web API 2.1 with BSON support turned on.

To accept a BSON response, create a BSON Deserializer for RestSharp like so

public class BsonDeserializer : IDeserializer
{
    public string RootElement { get; set; }
    public string Namespace { get; set; }
    public string DateFormat { get; set; }

    public T Deserialize<T>(IRestResponse response)
    {
        using (var memoryStream = new MemoryStream(response.RawBytes))
        {
            using (var bsonReader = new BsonReader(memoryStream))
            {
                var serializer = new JsonSerializer();
                return serializer.Deserialize<T>(bsonReader);
            }
        }
    }
}

Then, ensure your request accepts "application/bson"

var request = new RestRequest(apiUrl, verb);
request.AddHeader("Accept", "application/bson");

And add a handler for that media type

var client = new RestClient(url);
client.AddHandler("application/bson", new BsonDeserializer());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top