Wednesday, July 29, 2009

JavaScript TreeView component using MooTools library

Some time ago i wrote this TreeView component using the MooTools javascript library.
As far as i know there are not many treeviews around for MooTools, so i decided to put it up for grabs here.

Key Features:
- Load tree data from JSON file
- Load child nodes on demand using AJAX
- Select multiple nodes

View the demo here.
Download DotTech Tree v1.0.1: dottech.tree-1.0.1.zip.

UPDATE: Unfortunately the code is not available at the moment (i lost it and didnt have time to search for it yet)

/Ruud

Tuesday, July 28, 2009

PHP var_dump() method for C#

In PHP there is the var_dump() and print_r() function that displays the contents of an object.
Sometimes i miss this functionality in ASP.NET, especially when you are working with large objects and don't want to step into your code every time.
I came up with this method to list all the properties of a given object by name and value.
It also lists any child properties recursively, until it reaches a certain level of recursion (in this case it stops after 5 recursions).

using System;
using System.Text;
using System.Reflection;
using System.Collections;

public string var_dump(object obj, int recursion)
{
StringBuilder result = new StringBuilder();

// Protect the method against endless recursion
if (recursion < 5)
{
// Determine object type
Type t = obj.GetType();

// Get array with properties for this object
PropertyInfo[] properties = t.GetProperties();

foreach (PropertyInfo property in properties)
{
try
{
// Get the property value
object value = property.GetValue(obj, null);

// Create indenting string to put in front of properties of a deeper level
// We'll need this when we display the property name and value
string indent = String.Empty;
string spaces = "| ";
string trail = "|...";

if (recursion > 0)
{
indent = new StringBuilder(trail).Insert(0, spaces, recursion - 1).ToString();
}

if (value != null)
{
// If the value is a string, add quotation marks
string displayValue = value.ToString();
if (value is string) displayValue = String.Concat('"', displayValue, '"');

// Add property name and value to return string
result.AppendFormat("{0}{1} = {2}\n", indent, property.Name, displayValue);

try
{
if (!(value is ICollection))
{
// Call var_dump() again to list child properties
// This throws an exception if the current property value
// is of an unsupported type (eg. it has not properties)
result.Append(var_dump(value, recursion + 1));
}
else
{
// 2009-07-29: added support for collections
// The value is a collection (eg. it's an arraylist or generic list)
// so loop through its elements and dump their properties
int elementCount = 0;
foreach (object element in ((ICollection)value))
{
string elementName = String.Format("{0}[{1}]", property.Name, elementCount);
indent = new StringBuilder(trail).Insert(0, spaces, recursion).ToString();

// Display the collection element name and type
result.AppendFormat("{0}{1} = {2}\n", indent, elementName, element.ToString());

// Display the child properties
result.Append(var_dump(element, recursion + 2));
elementCount++;
}

result.Append(var_dump(value, recursion + 1));
}
}
catch { }
}
else
{
// Add empty (null) property to return string
result.AppendFormat("{0}{1} = {2}\n", indent, property.Name, "null");
}
}
catch
{
// Some properties will throw an exception on property.GetValue()
// I don't know exactly why this happens, so for now i will ignore them...
}
}
}

return result.ToString();
}

For my example i used an object called Category, but this can be an instance of any class.
Category has a few basic properties and one called Parent which holds another Category object (so we have child properties).
I call the method like this:

Category category = LoadCategory(123);
Response.Write(var_dump(myObject, 0)); // Always start at recursion 0,
// you might want to add an override
// that sets this argument by default

The output of this example is:

CategoryId = 685
ParentId = 287
Name = "Beans"
Description = ""
Parent = MyProject.Data.Category
|...CategoryId = 287
|...ParentId = 174
|...Name = "Cheap food"
|...Description = ""
|...Parent = MyProject.Data.Category
| |...CategoryId = 174
| |...ParentId = 173
| |...Name = "Food"
| |...Description = ""
| |...Parent = MyProject.Data.Category
| | |...CategoryId = 173
| | |...ParentId = 0
| | |...Name = "Things to eat"
| | |...Description = ""
| | |...Parent = null
| | |...Count = 0
| |...Count = 0
|...Count = 13
Count = 0
TestList = System.Collections.Generic.List`1[MyProject.Data.Category]
|...TestList[0] = MyProject.Data.Category
| |...CategoryId = 1
| |...ParentId = 0
| |...Name = "Bla"
| |...Description = ""
| |...Count = 0
|...Count = 1

It's not exactly PHP's var_dump() method, but it works for me! :)
I might expand it some day so it dumps array/list elements too and maybe add some XHTML formatting.

Update on 29-07-2009:
Added support for collection properties.

/Ruud

Reseed the identity column of a table in SQL Server

When you want the identity field of a table to be reset (start with id 1 again), execute the following SQL query:

DBCC CHECKIDENT (tableName, reseed, 0)

Where "tableName" is replaced by the name of your table and the 0 is the new seed.

/Ruud

Target elements with ids that contain special characters using jQuery

Let's say you have some HTML elements with ids like this one:

<div id="form~myform$div~mydiv[1]#value"></div>

And you would like to target this element using jQuery.
This will not work because of the special characters used in the element's id.
If you execute the following jQuery:

$("div").each(function() {
var divId = this.id;
var jQueryFound = $('#' + this.id).length;

alert("Div id is '" + divId + "' and jQuery found " + jQueryFound);
});

The result is: Div id='form~myform$div~mydiv[1]#value' and jQuery found 0.
JQuery cannot find the element id because it contains meta-characters that jQuery parses as part of the selector.
To solve this problem i wrote a method which escapes the special characters so jQuery parses them as part of the id.

var jEscape = function(jquery) {
jquery = jquery.replace(new RegExp("\\$", "g"), "\\$");
jquery = jquery.replace(new RegExp("\~", "g"), "\\~");
jquery = jquery.replace(new RegExp("\\[", "g"), "\\[");
jquery = jquery.replace(new RegExp("\\]", "g"), "\\]");
jquery = jquery.replace(new RegExp("#", "g"), "\\#");
return jquery;
};

Now execute the following code to see that it works:

$("div").each(function() {
var divId = this.id;
var escapedId = jEscape(this.id);
var jQueryFound = $('#' + escapedId).length;

alert("Div id is '" + divId + "' which is escaped to '" + escapedId + "' and jQuery found " + jQueryFound);
});

The result is: Div id is 'form~myform$div~mydiv[1]#value' which is escaped to 'form\~myform\$div\~mydiv\[1\]\#value' and jQuery found 1.

If you want to escape all the possible jQuery meta-characters, expand the method to escape these: ;&,.+*':"!^()=>|/

/Ruud

Monday, July 27, 2009

Generic XML deserializer method

For one of my projects i needed to deserialize several XML files to objects of different data types.
Therefore i wrote this generic deserialization method:

public static T Deserialize(XmlReader xmlReader, string rootElement)
{
T result;

XmlRootAttribute root = new XmlRootAttribute(rootElement);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T), root);
result = (T)xmlSerializer.Deserialize(xmlReader);

return result;
}

To use it, you first load your XML file into an XmlReader object and call the method like this:

MyTargetType deserialized = Deserialize(xmlReader, "startnode");
(ignore the type name being upper case in my example, it's caused by the code highlighter)

I will post some more later about how you can let your application use its configuration to decide what data type specific XML files should be deserialized to.
This can be very usefull when you have an application that deserializes multiple XML feeds and you want the list of feeds to be configurable outside of the code.

/Ruud

Remove all non-letter characters from a string

Problem: You have a string that may contain various special characters and you need it to contain only letters and digits.
...and you don't want to use regular expressions ;-)

Solution: There are problably a hundred ways to do this, but if you are using C# 3.0 or higher, there is a very quick solution that costs you just one line of code.
First i will show the slightly larger version of the code snippet which explains the workings better:

string dirtyString = "http://www.dottech.nl/#?this%20is%20dirty!";
string cleanString = String.Empty;

// Convert the string to a character array so we can load it into a List
char[] dirtyChars = dirtyString.ToCharArray();

// Create a character list and load the dirtyChars array
List<Char> characters = new List(dirtyChars);

// Use the List's ForEach method to iterate through the characters
characters.ForEach(delegate(char c)
{
if (Char.IsLetter(c))
{
cleanString += c.ToString();
}
});

return cleanString; // "httpwwwdottechnlthisisdirty"

Now, when i wrote this i figured it had to be a little more compact.
So i used a Lambda Expression which is a new feature in C# 3.0 and changed the ForEach line to this:

characters.ForEach(c => cleanString += (Char.IsLetter(c)) ? c.ToString() : String.Empty);

And after some more compacting i ended up with the final snippet:

new List<Char>(dirtyString.ToCharArray()).ForEach(c => cleanString += (Char.IsLetter(c)) ? c.ToString() : String.Empty);

Although it might look complex to someone who sees that line of code for the first time, i still think it's a pretty maintainable line of code as long as you put some comments above it explaining how dirtyString is the input and cleanString the output.

/Ruud

Welcome to Ruud.Tech, a blog for software engineers

Since i regularly stumble upon and come up with nifty code snippets and solutions which might be usefull for other software engineers, i have decided to start this blog and collect them here.

Enjoy!

/Ruud