# Sunday, August 12, 2007

In my previous article I talked about the hunt for a good JSON parser/serializer. For my current project I only needed a serializer to generate JSON from any .NET object, so for now it’s a bit overkill to use a full blown JSON library.

After looking at the specs for JSON, I figured it couldn’t be too hard to write a JSON serializer in C#. Not only was it not that hard, it was very short too: about 100 lines of code (well, 110 without the empty lines).

The serializer can handle any regular data type, including DateTime (for which there is no standard in JSON).

Here it is: (feel free to use it for anything you like)

 

public class JSONSerializer
{
    private readonly StringBuilder _output = new StringBuilder();

    public static string ToJSON(object obj)
    {
        return new JSONSerializer().ConvertToJSON(obj);
    }

    private string ConvertToJSON(object obj)
    {
        WriteValue(obj);

        return _output.ToString();
    }

    private void WriteValue(object obj)
    {
        if (obj == null)
            _output.Append("null");
        else if (obj is sbyte || obj is byte || obj is short || obj is ushort || obj is int || obj is uint || obj is long || obj is ulong || obj is decimal || obj is double || obj is float)
            _output.Append(Convert.ToString(obj,NumberFormatInfo.InvariantInfo));
        else if (obj is bool)
            _output.Append(obj.ToString().ToLower());
        else if (obj is char || obj is Enum || obj is Guid)
            WriteString("" + obj);
        else if (obj is DateTime)
            _output.Append("new Date(" + ((DateTime)obj - new DateTime(1970,1,1)).TotalMilliseconds.ToString("0") + ")");
        else if (obj is string)
            WriteString((string)obj);
        else if (obj is IDictionary)
            WriteDictionary((IDictionary)obj);
        else if (obj is Array || obj is IList || obj is ICollection)
            WriteArray((IEnumerable)obj);
        else
            WriteObject(obj);
    }

    private void WriteObject(object obj)
    {
        _output.Append("{ ");

        bool pendingSeparator = false;

        foreach (FieldInfo field in obj.GetType().GetFields(BindingFlags.Public|BindingFlags.Instance))
        {
            if (pendingSeparator)
                _output.Append(" , ");

            WritePair(field.Name, field.GetValue(obj));

            pendingSeparator = true;
        }

        foreach (PropertyInfo property in obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            if (!property.CanRead)
                continue;

            if (pendingSeparator)
                _output.Append(" , ");

            WritePair(property.Name,property.GetValue(obj, null));

            pendingSeparator = true;
        }

        _output.Append(" }");
    }

    private void WritePair(string name, object value)
    {
        WriteString(name);

        _output.Append(" : ");

        WriteValue(value);
    }

    private void WriteArray(IEnumerable array)
    {
        _output.Append("[ ");

        bool pendingSeperator = false;

        foreach (object obj in array)
        {
            if (pendingSeperator)
                _output.Append(',');

            WriteValue(obj);

            pendingSeperator = true;
        }

        _output.Append(" ]");
    }

    private void WriteDictionary(IDictionary dic)
    {
        _output.Append("{ ");

        bool pendingSeparator = false;

        foreach (DictionaryEntry entry in dic)
        {
            if (pendingSeparator)
                _output.Append(" , ");

            WritePair(entry.Key.ToString(),entry.Value);

            pendingSeparator = true;
        }

        _output.Append(" }");
    }

    private void WriteString(string s)
    {
        _output.Append('\"');

        foreach (char c in s)
        {
            switch (c)
            {
                case '\t': _output.Append("\\t"); break;
                case '\r': _output.Append("\\r"); break;
                case '\n': _output.Append("\\n"); break;
                case '"': 
                case '\\': _output.Append("\\" + c); break;
                default:
                    {
                        if (c >= ' ' && c < 128)
                            _output.Append(c);
                        else
                            _output.Append("\\u" + ((int) c).ToString("X4"));
                    }
                    break;
            }
        }

        _output.Append('\"');
    }
}
kick it on DotNetKicks.com
Sunday, August 12, 2007 9:30:00 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [13] -

I’ve been using AjaxPro for a few years now, and I must say that I have been very happy with it. It was even integrated with ProMesh.NET, meaning you just had to call RegisterTypeForAjaxPro() and the method stubs were being generated in the HTML output.

I was in the process of checking out some JavaScript frameworks, when I came across jQuery. Pretty cool stuff, although not that much different from Mootools, which I have been using for a few months. The Ajax stuff in jQuery is pretty easy to use and started playing around with it until… Hmm, I am moving away from the point of this article.

Anyway, not that all of this matters, but I started thinking about how hard it would be to offer the same functionality that AjaxPro offered, all integrated in the ProMesh.NET framework.
Calling the server methods was a no-brainer, because the framework already supports calling specific methods on Controller objects. The “hard” part was returning objects to the client as  JSON strings. I didn’t feel like writing my own JSON generator, so I started checking out some open-source stuff.

I found the following products:

All of these did exactly what I needed, so it was hard to choose. What was very unusual, is that one of these products, LitJSON, had a public domain license (i.e. no license at all). Not that the licensing for the other offerings was too restrictive to be included in ProMesh.NET, the thought of not having to worry at all about licensing made me decide to take a better look at LitJSON. The product seems to be very solid and well written, so I added it to the source tree of ProMesh.NET. I will include it with the 1.1.0 release of ProMesh.NET, but with a notice in the release notes that the JSON stuff hasn’t been tested as thoroughly as it should have been.

So, to make a long story short: ProMesh.NET now supports native Ajax method calls using jQuery or another JavaScript framework. Currently, only the jQuery JavaScript provider has been included in the latest build, but you can plug in any provider you like (using the IAjaxProvider interface).

kick it on DotNetKicks.com
Sunday, August 12, 2007 1:52:42 AM (W. Europe Daylight Time, UTC+02:00)  #    Comments [3] -

# Wednesday, August 08, 2007

Scott Bellware wrote an interesting article “Monorail vs. Rails Isn't a Meaningful Question” which touches the subject of choosing a technology for building web applications.

The question “if you're building web apps on .NET, what leads you to assume that you should be building on .NET?” came up twice in his post. While this is a question a technologist might ask, it is a no-brainer for the stake-holders.

Think about this: As a stake-holder, why would you use Ruby (on Rails) when it is at least 100 times harder to find Ruby developers than it is to find good .NET developers? You wouldn’t. Even if I was a die-hard Ruby enthusiast, and I needed to build a “real” web application my company depended on, I would never pick Ruby on Rails.

So obviously .NET is a safe choice, but that doesn’t necessarily mean you should use the ASP.NET framework. There are other (better?) frameworks available for building web applications in .NET (I even doubt that the Microsoft website is using ASP.NET Web Forms for all its content). It’s not that hard to teach a .NET developer how to use MonoRail or ProMesh.NET or (…), but it is a lot harder to make a C# developer use Ruby (on Rails).

Ruby may be the better technology for web apps, .NET seems (for now) to be a better (business) choice for real web applications.

kick it on DotNetKicks.com
Wednesday, August 08, 2007 12:47:31 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [17] -
 |  |  | 
# Monday, August 06, 2007

A few days ago I activated “MyBrand” on FeedBurner, which allows you to use your own domain name instead of “feeds.feedburner.com”. I chose to use “feeds.activa.be”, and indeed, this worked as advertised. (I had to change some DNS settings, but that was a no-brainer)

To my surprise, I saw this on my FeedBurner stats page under “Uncommon Uses”.

Feedburner_uncommon

WTF??

It seems FeedBurner treats my “MyBrand” URL “http://feeds.activa.be/activa” as an “uncommon use”

Why my original RSS feed is also there is another mistery to me…

kick it on DotNetKicks.com
Monday, August 06, 2007 10:35:20 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [1] -

One of the most powerful features in .NET is the ability to use reflection to do all kinds of neat stuff at runtime, like

  • Find out what properties, fields, methods, etc. are in a class
  • Create objects without knowing their type at compile time
  • Call methods by name (even private ones)
  • Check attributes on classes, methods, fields, …

The web framework I built over the last few years, ProMesh.NET, relies on reflection for a lot of the features it offers. Often though, I am asked if the heave use of reflection doesn’t have a significant impact on performance.

My answer usually is: YES, but it doesn’t matter. Now you probably think that I don’t care about performance or that I’ve had too much too drink. None of the above. I’ll explain:

In ProMesh.NET, there’s a feature that allows you to just declare session properties in your class that will be constructed at runtime, like this:

   private SessionProperty<string> _mySessionVar1;
or
   private SessionProperty<string> _mySessionVar2 = new SessionProperty<string>();

You don’t have to initialize _mySessionVar1. The framework uses reflection to construct the object.

Creating _mySessionVar1 is about 20 times slower than creating _mySessionVar2. Shocking? Yes. Unacceptable? No!

The reason why it is not unacceptable is that it takes 2.2 µs (microseconds) to create _mySessionVar1, and 0.12 µs (microseconds) to create _mySessionVar2. These figures include dynamically iterating the over the class members, determining their type and looking up the appropriate constructor. This is the simplified code which creates the fields at runtime:

foreach (MemberInfo member in GetType().GetMembers())
{
if (member is FieldInfo)
{
FieldInfo field = (FieldInfo) member;

ConstructorInfo constructor =
field.FieldType.GetConstructor(Type.EmptyTypes);

field.SetValue(this, constructor.Invoke(new object[0]));
}
}

Considering this happens when a web page is requested, which usually involves some database access, a little disk access and some other time-consuming stuff, a complete web page request takes between 50ms and 2000ms. Assuming we have 20 session variables to construct at runtime, the overhead is … between 0.08% (worst case) and 0.002%.

So, yes it is MUCH slower, but it doesn’t matter. (not for applications of this kind)

kick it on DotNetKicks.com
Monday, August 06, 2007 8:48:01 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [3] -
 |  |  |  |  |