I’ve some legacy code where stuff have to be passed with querystring, because we need to issue Get request to the server, and I need to pass various set of parameters for some reporting functions, but those parameters have 20 field, and are somewhat used as a tree. I decided to serialize everything and pass the result with querystring using HttpUtility.UrlEncoding… the result was frustrating because the url are simply too long.
So I begin investigating on how to reduce data size of serialized object to be encoded with UrlEncode. This is the first solution
1
2
3
4
5
6
| using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter f = new BinaryFormatter();
f.Serialize(ms, param);
serialized =HttpUtility.UrlEncode(ms.ToArray());
}
|
For a typical object it uses 3264 charachters.. ouch too much, so I try with compression
1
2
3
4
5
6
7
8
9
| using (MemoryStream ms = new MemoryStream())
using (GZipStream gzstream = new GZipStream(ms, CompressionMode.Compress))
{
BinaryFormatter f = new BinaryFormatter();
f.Serialize(gzstream, param);
gzstream.Flush();
gzstream.Close();
serialized = HttpUtility.UrlEncode(ms.ToArray());
}
|
With compression I decreased the size to 2204 chars, still too much but If I look at the output string it is a really mess of escaping chars. UrlEncoding is not so good in encoding binary stream, a better solution is Base64
1
2
3
4
5
6
7
8
9
| using (MemoryStream ms = new MemoryStream())
using (GZipStream gzstream = new GZipStream(ms, CompressionMode.Compress))
{
BinaryFormatter f = new BinaryFormatter();
f.Serialize(gzstream, param);
gzstream.Flush();
gzstream.Close();
serialized = HttpUtility.UrlEncode(Convert.ToBase64String(ms.ToArray()));
}
|
I gzipped the serialized stream, then convert in Base64 and finally encoded with UrlEncode, the result is 1402 chars, really better but I want a string less than 1000 chars if possible. Since I know that DataContractSerializer produces a very compact string, I simply used it with a little trick
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| using (StringWriter sw = new StringWriter())
{
DataContractSerializer serializer = new DataContractSerializer(param.GetType());
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.Indent = true;
settings.NewLineOnAttributes = true;
using (XmlWriter writer = XmlWriter.Create(sw, settings))
{
serializer.WriteObject(writer, param);
}
using (MemoryStream ms = new MemoryStream())
using (GZipStream gzstream = new GZipStream(ms, CompressionMode.Compress))
{
Byte[] allcontent = Encoding.UTF8.GetBytes(sw.ToString());
gzstream.Write(allcontent, 0, allcontent.Length);
gzstream.Flush();
gzstream.Close();
serialized = HttpUtility.UrlEncode(Convert.ToBase64String(ms.ToArray()));
}
}
|
I use DataContractSerializer to have a xml serialized stream, then I encode in UTF8 with Gzip compression, and finally I convert to Base64 and UrlEncode it, the result is 948 chars :) quite good, because now I’m under 1000 chars, respect the first version with plain binary serialization that was 3264 chars.
Alk.
Tags: Microsoft.Net