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: , , ,

Getting the Server-Side Offset to the JavaScript Epoch in C#

3. September 2009 16:50

Just in case anyone else needs it, here's my method for getting the millisecond offset of a server's local time to UTC time in milliseconds, for use in client-side JavaScript.

private int ServerSideJsUtcOffset
{
    get {
        DateTime epoch = new DateTime(1970,1,1);
        int offset = (int)epoch.ToUniversalTime().Subtract(epoch).TotalMilliseconds;
        return offset;
    }
}

There's really not much to it, it's mainly so that I can handle converting serialized dates to a proper local time on the client. The DateTime objects in question are stored in a database as the UTC date-time, via an ORM tool, and sent to the client with System.Web.Script.Serialization.JavaScriptSerializer. All the server-side code uses the same ORM tool, and all the client-side JSON is processed via the same local parser. So it was simply easier adjusting the client-side parser than it was to adjust the server-side class hierarchy.

I should note that I could have set the initial date to DateTime.Now instead of implicitely using the JS epoch, as the difference would be the same for any localized DateTime, just felt the clarity was worth it.

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: ,

Handling Scripts in ASP.Net MVC

29. June 2009 15:39

Okay, so you have a bunch of script references, some added via your master template, others in your views.  You'd also like to be able to handle script adds in your partial views.  The problem is, you don't want your views, and partial views to know about the implementation details.  What I am going to do, is outline my solution for adding needed scripts into a given view/output without having duplicate script tags, and allowing each master, view, and partial to call for all the scripts it will need. More...

C# Tip: Creating an Octal String from a Byte in C#

3. December 2008 18:19

Okay, so C# (.Net) has some awesome functionality for creating a hex string from a numeric value.  But what if you need an octal string for a binary value.  The real key is realizing that you need to move the value by 3 bits at a time for each octal number, and to XAND the value by 7 which is the highest value an octal number can hold. More...

Tags:

C# Tip: Use StringBuilder

5. November 2008 18:31

Okay, as an extension to the last post on String.Format, I'm doing a quick introduction to the System.Text.StringBuilder class.  Why, you ask.  Because when you append to a string, there is a lot of memory being allocated, transferred and dumped behind the scenes.  Say you have a string of "My string is" and you want to append " cool." what happens is a new string is allocated in memory, with enough space for the original string, and the appended value.  Then the original string is copied to the beginning, and the appended string is copied after.  This is very inneficient.  StringBuilder pre-allocates additional space, and handles the concatenation behind the scenes. More...

C# Tip: Don't Concatenate, Use String.Format

24. October 2008 09:57

Something that tends to annoy me, is seeing a ton of string concatenation, such as below.

string mystring = "<a href="\">" +
    ResourceHelper.GetString("somestr", SiteHelper.GetCurrentCulture()) +
    "</a>"; 

More...

Tags: , ,

Setting up mod_mono (ASP.Net 2.0) on Ubuntu 7.10 (Gutsy Gibbon)

9. February 2008 17:57

After spending a day on this, I figured it would be worthwhile information for anyone that may be interested in configuring mod_mono2 (ASP.Net) for Ubuntu Gutsy.  I'm personally using an Ubuntu JeOS base configuration.  You may want to install your database of choice (mySQL, Firebird SQL, PostgreSQL, etc) in addition to other supported modules for apache2. 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.