Wednesday, November 23, 2011

Compressing and Decompressing Text Strings using GZipStream

Simply wanted to pass a text to client and the receive it back again. Something like the old viewstate concept. I searched the web for ready to use piece of code that compress the text into byte[] and vice versa but I failed to find a working source code, so I wrote one.

Here it is:

public class Zip
    //public static Encoding Encoding = System.Text.Encoding.Unicode;
    public static byte[] Compress(string text, Encoding Encoding = null)
        if (text == nullreturn null;
        Encoding = Encoding ?? System.Text.Encoding.Unicode;            // If the encoding is not specified use the Unicode
        var textBytes = Encoding.GetBytes(text);                        // Get the bytes according to the encoding
        var textStream = new MemoryStream();                            // Make a stream of to be feeded by zip stream
        var zip = new GZipStream(textStream, CompressionMode.Compress); // Create a zip stream to receive zipped content in textStream
        zip.Write(textBytes, 0, textBytes.Length);                      // Write textBytes into zip stream, then zip will populate textStream
        return textStream.ToArray();                                    // Get the bytes from the text stream
    public static string Decompress(byte[] value, Encoding Encoding = null)
        if (value == nullreturn null;
        Encoding = Encoding ?? System.Text.Encoding.Unicode;                // If the encoding is not specified use the Uncide
        var inputStream = new MemoryStream(value);                          // Create a stream based on input value
        var outputStream = new MemoryStream();                              // Create a stream to recieve output
        var zip = new GZipStream(inputStream, CompressionMode.Decompress);  // Create a stream to decompress inputStream into outputStream
        byte[] bytes = new byte[4096];
        int n;
        while ((n = zip.Read(bytes, 0, bytes.Length)) != 0)                 // While zip results output bytes from input stream
            outputStream.Write(bytes, 0, n);                                // Write the unzipped bytes into output stream
        return Encoding.GetString(outputStream.ToArray());                  // Get the string from unzipped bytes

Monday, November 21, 2011

MVC Tips #1, Passing HTML or Javascript as Data

Sometimes you need to render an html to output which the source of HTML is from your model. For security reasons rendering html directly from data requires to be explicitly requested, here is the 2 scenarios for doing so:

If your model has a property which contains HTML content you add the AllowHtml property before the property. By doing so you inform the MVC that you expect html content in that property.
Although the it is named AllowHtml it also works for JavaScript.

When rendering a Razor view to allow html content be rendered to output use @Html.Raw(Model.HtmlContent).

WARNING By using any of the above technique you need to make sure that the HTML or JavaScript content is safe. So if the data comes from some untrusted source you application will become vulnerable to attacks.

WARNING 2 Also pay attention to fact that AllowHtml also allows JavaScript, so dont assume that by applying this attribute only safe html code will be passed to client.

Note :
If you have a custom model binder and use pass the html values in your model, you may receive this exception:
A potentially dangerous Request.Form value was detected from the client
I found a solution for this problem at this Martijn Boland's blog post. which worked fine for me and you can learn about why this problem exists and how the solution works.

Tuesday, November 1, 2011

Asp.Net MVC : Setting Model as string and avoiding Illegal Characters in Path

If you for every reason need to set a page's model type to be string type, then you may face this exception:

Illegal Characters in path

Which seem to be weird, or you even may dont understand that the cause of the above problem is the Model type being string.
Actually the reason that you get the above exception is that in your Controller you as usual called the View method passing the model as the only argument and the model value is a string. But what you may have not pay attention to is that View method also has another override which accepts an string as the view name. So if you pass the model like this code:

return View("myStringModel");

In the above code you specified to go to page with the name "myStringModel" and such a page does not exists. Solution: My suggestion is to select the right overload by specifying the argument explicitly, like the below code:

return View(model: "myStringModel");