I am using Marc Gravell's Protobub-Net to serialize and deserialize objects.
I am looking for the most efficient way to transfer data through an http://
request.
Here what I have done so far:
public string ProtobuffToString()
{
Dictionary<int, decimal> List1 = new Dictionary<int, decimal>();
List1.Add(2018, 1.2m);
List1.Add(2017, 1.4m);
List1.Add(2016, 1.9m);
using (var stream = new MemoryStream())
{
ProtoBuf.Serializer.Serialize(stream, List1);
return Convert.ToBase64String(stream.ToArray());
}
}
public async System.Threading.Tasks.Task<string> ReadProtobuffAsync()
{
using (System.Net.Http.HttpClient client = new System.Net.Http.HttpClient())
using (System.Net.Http.HttpResponseMessage response = await client.GetAsync("http://localhost:53204/ProtobuffToString")) //<= Will call ProtobuffToString() above
using (System.Net.Http.HttpContent content = response.Content)
{
string result = await content.ReadAsStringAsync();
byte[] resultByte = Convert.FromBase64String(result);
using (var stream = new MemoryStream(resultByte))
{
return JsonConvert.SerializeObject(ProtoBuf.Serializer.Deserialize<Dictionary<int, decimal>>(stream));
}
}
}
Can I do it better?
And is it better/faster than to transfer it from json/Json.Net?
Maybe yes because the data transfer will be smaller and the serialization/deserialization faster.
Can i do it better?
Protobuf is a binary serialization format that is optimized for (de-)serialization and a low-footprint transfer. By converting the data to Base64 you add another conversion layer and increase the footprint of the transmission.
And is it better/faster than to transfer it from json/Json.Net?
There is no reasonable argument that would support that claim. Reiterating my previous statement, Protobuf is highly optimized, whereas JSON is some sort of trade-off that is not very efficient to serialize, nor very well readable.
Having said that, have a small example, how to send your Protobuf via HTTP
HttpClient client = new HttpClient();
using (var stream = new MemoryStream())
{
// serialize to stream
ProtoBuf.Serializer.Serialize(stream, List1);
stream.Seek(0, SeekOrigin.Begin);
// send data via HTTP
StreamContent streamContent = new StreamContent(stream);
streamContent.Headers.Add("Content-Type", "application/octet-stream");
var response = client.PostAsync("http://what.ever/api/upload", streamContent);
}
If you'd like to receive Protobuf, you could modify your snippet like
using (System.Net.Http.HttpClient client = new System.Net.Http.HttpClient())
using (System.Net.Http.HttpResponseMessage response = await client.GetAsync("http://localhost:53204/ProtobuffToString")) //<= Will call ProtobuffToString() above
using (System.Net.Http.HttpContent content = response.Content)
using (var memoryStream = new MemoryStream())
{
await content.CopyToAsync(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin); // reset stream
return ProtoBuf.Serializer.Deserialize<Dictionary<int, decimal>>(memoryStream); // assuming that you return the Dictionary, not a string
}
Actually I don't see why you wanted to return the string
instead of the Dictionary<int, decimal>
from ReadProtobuffAsync
. I'd recomment to drop the Dictionary
altogether and use meaningful protobuf definitions and corresponding classes, because this is the really strong point of Protobuf.