101 reasons why Java is NOT better than .Net in 2010

27. May 2010 10:19

Okay, I'm getting really tired of seeing posts like this one... So I figured I'd take some time to debunk the thing.

More...

Tags: , , ,

HttpContext Items Collection

19. April 2010 11:07

Just a short little post, I do intend to followup my last post with a post with code on combining/minifying your JavaScript and CSS, this just caught my attention, and wanted to mention it. 

In the process of doing some technical screenings, it is really suprising how many people don't understand or even know about the HttpContext Items Collection in ASP.Net.  More...

Compressing Bytes In .Net

20. August 2009 10:57

Okay, this started when I wanted to store a bit of JSON that gets rendered into the ASP.Net cache.  Each entry would be unique to a given user, and I wanted to save a little memory, each entry would be about 8KB in size.  I looked into this and found the System.IO.Compression namespace that is available in .Net 3.5.  I created a small class with some helper extensions to be able to compress/decompress an array of byte, and handle to/from a native string.  Here's what I came up with.


CompressionExtensions.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Compression;

namespace Sample
{
    public static class CompressionExtensions
    {
        const int KB = 1024;

        public static byte[] Compress(this byte[] input)
        {
            using (var ms = new MemoryStream(input.Length + 8))
            {
                ms.Write(BitConverter.GetBytes(input.Length), 0, 4); //record original length

                if (input.Length < KB)
                {
                    //if less than 1KB, don't compress original
                    ms.Write(input, 0, input.Length);
                    return ms.ToArray().Take(input.Length + 4).ToArray();
                }

                //compress the original input
                using (var ds = new DeflateStream(ms, CompressionMode.Compress))
                {
                    //send the original input to the compressed stream
                    ds.Write(input, 0, input.Length);

                    //add null padding. the decompress gets wonky without it.
                    ds.Write(new byte[4], 0, 4);
                    ds.Flush();
                    ms.Flush();
                    return ms.ToArray();
                }
            }
        }

        public static byte[] Decompress(this byte[] input)
        {
            if (input == null || input.Length < 4)
                throw new ApplicationException("Invalid compressed bytes, no length header.");
        
            var bitlen = BitConverter.ToInt32(input, 0);

            //if less than 1KB, return the non-compressed original
            if (bitlen < KB) return input.Skip(4).ToArray();

            var buffer = new byte[bitlen];
            using (var ms = new MemoryStream(input.Length - 4))
            {
                ms.Write(input, 4, input.Length - 4);
                ms.Flush();
                ms.Seek(0, SeekOrigin.Begin);
                using (var ds = new DeflateStream(ms, CompressionMode.Decompress))
                {
                    //this always returns a -1 for the first read
                    //    subsequent reads will work properly
                    ds.ReadByte();

                    //read the input stream into the return buffer
                    if (bitlen > ds.Read(buffer, 0, bitlen))
                        throw new ApplicationException("Invalid compressed bytes.");
                }
            }

            //only return the number of bytes originally saved, trim excess
            return buffer;
        }

        public static byte[] ToCompressedBytes(this string input)
        {
            return Encoding.UTF8.GetBytes(input).Compress();
        }

        public static string ToDecompressedString(this byte[] b)
        {
            return Encoding.UTF8.GetString(b.Decompress());
        }
    }
}

I found that without adding some padding of at least two null bytes, the decompression of the data would sometimes give me an invalid final byte. I also push in a 4-byte length header for a sanity check. This also helps me to not compress anything under 1KB in size, where compression really doesn't work very well.

The conversion of the string to UTF8 helps more with strings that will mostly contain values within the ASCII character set. It is worth noting that if there are mostly multibyte characters, the byte array itself could get bloated. For my usage, I'm getting an 8KB string down to around 2KB, you could extend this to support UTF8/Unicode encoding by appending a character to the end before compressing. This may be useful if the string is >2KB and more than 1/3 is multibyte characters, this would take a little more CPU time to inspect the input string in this case.

Your milage may vary. Void where prohibited. Quantities limited. Some restrictions may apply. Batteries not included.

Tags: ,

Apollo.Common in Codeplex

19. December 2008 04:53

The past few weeks, I've been working on Apollo.Common, which is meant to provide some easier to use functionality to enterprise applications.  A lot of this functionality, and more is provided by the MS PnP team's Microsoft Enterprise Library.  However, ent-lib tends to be overly complex, difficult to use, and require a lot of customization before you can get moving.  I want Apollo.Common to be easy to use, implement and deploy with a minimal learning curve. More...

Refactoring

19. November 2008 19:29

Okay, there are two main reasons to refactor.  The first is clarity of code.  Since we have a working base, we can now concentrate on making our logic readable, breaking major blocks of code into separate methods, as well as possibly change how certain calls work.  The second major reason to refactor is for performance or scale.  One needs to first realize that scale and performance aren't always the same thing.  Scaling is about consistency, where performance is about speed.  The two often have the same result, but not always. More...

Tags:

MySite - Part 2 - Theming Support

13. November 2008 14:55

Okay, I lied.  I really wanted to figure out how to get theming to work the way I wanted. As you can see to the right, I created a "Theme" folder, where I have a "Default" and in this case a "Red" theme.  Under the theme's folder, I moved the Content, and Views folders.  My goal was to allow for a fallback to using a View from the Default theme, but still allow for the appropriate masterpage to be applied from the theme's folder if one existed.  In this case, you can see that there is an Index view for the Home controller within the Default theme, but there is no matching view in the Red theme. More...

Tags: , , ,

MySite - Part 1

11. November 2008 22:14

My goal is to create a personal website application that implements the features needed, and wanted for someone who wants to create a personal site that extends beyond just a blogging engine.  I've been wanting to work with ASP.Net MVC and some other technologies, so I'll be focusing on using them in MySite. More...

Tags: , , ,

The Data Hive

11. November 2008 00:19

I've had some ideas bouncing around in the back of my head for a few days now.  One is that when using an application, specifically a large-scale web application, having a traditional RDBMS backend is a point of limitation in terms of scale.  RDBMS systems are really good for being able to aggregate data, and create reporting interfaces, but it isn't so great from being able to use structured object data on the front end.  Now I'm talking about going beyond ORM mappers, and even beyond an Object Database here.  What I see coming in the future is a Data Hive. More...

Tracker1

Michael J. Ryan aka Tracker1

My name is Michael J. Ryan and I've been developing web based applications since the mid 90's.

I am an advanced Web UX developer with a near expert knowledge of JavaScript.