Pass a serialized object in querystring with less chars

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