and has 0 comments
Don't go all "Oh no, not another Beowulf remake!" on me. This is a book that was written in 1971 by John Gardner, presenting the story of Beowulf through the eyes of Grendel. But it is not really the same story, just uses it as a scaffold for the philosophical ideas that he wanted to expose.


Structured into 12 chapters - each for a year in Grendel's life, each for a description of a philosophical current, each for an astrological sign - the book is not an easy one to understand, albeit pretty short. The language is modern and the wording is clear, but the underlying ideas need time and brain power to process, so don't read it in short bursts when you feel bored. Give it what it needs.

In the book, Grendel is not an animal monster, a thing with no thinking, quite the opposite. He is intelligent, articulate, philosophical, all these qualities being given to him at birth, not as a merit to anyone. He is hopelessly depressed and malevolent. He sees life and existence as meaningless, all the Universe a hollow illusion, a thing set to hurt him, set him apart, mock him. It is really easy to identify with him and to feel his feelings, while in the same time despise what he does and why he does it. Grendel is the part of us which we hate and which hates itself.

Enough, though, the book has bad parts as well. The occasional poem lyrics are meaningless in this book. The ending is confused and confusing. I would have liked a clearer ending, that's for sure. And also, it is hard to understand the book without at least knowing the Beowulf story and researching a bit from the Wikipedia article to find out what are the philosophical references hidden in each chapter. But then again, it was never a simple book, and the research (even if I haven't found time to do it) is worth it.

There was an animation film made in Australia in 1981 and featuring Peter Ustinov called Grendel Grendel Grendel which was based on the book, although I haven't been able to get my hands on it. It was partly musical as well, as expected in such a period, ugh!

If you are interested in finding out more about the meanings in the book and discussing about it, here is a link: The Grendel Board.

Update 19 February 2016:
I've done the test again, using another computer and .Net 4.6.1. The speed of filling the DataTableReplacement class given at the end of the article, plus copying the data into a DataTable object is 30% faster than using a DataTable directly with BeginLoadData/EndLoadData and 50% faster than using DataTable without the LoadData methods.

Now for the original post:

It was about time I wrote a smashing IT entry. Here is to the obnoxious DataTable object, something about I have written before of bugs and difficulty in handling. Until now I haven't really thought about what kind of performance issues I might face when using it. I mean, yeah, everybody says it is slow, but how slow can it be? Twice as slow? Computers are getting faster and faster, I might not need a personal research into this. I tried to make a DataTable replacement object once and it was not really compatible with anything that needed DataTables so I gave up. But in this article I will show you how a simple piece of code became 7 times faster when taking into account some DataTable issues.

But let's get to the smashing part :) I was using C# to transform the values in a column from a DataTable into columns. Something like this:

Name Column Value
George Money 100
George Age 31
George Children 1
Jack Money 150
Jack Age 26
Jack Children 0
Jane Money 300
Jane Age 33
Jane Children 2



and it must look like this:

Name Money Age Children
George 100 31 1
Jack 150 26 0
Jane 300 33 2



I have no idea how to do this in SQL, if you have any advice, please leave a comment.
Update: Here are some links about how to do it in SQL and SSIS:
Give the New PIVOT and UNPIVOT Commands in SQL Server 2005 a Whirl
Using PIVOT and UNPIVOT
Transposing rows and columns in SQL Server Integration Services

Using PIVOT, the SQL query would look like this:

SELECT * 
FROM #input
PIVOT (
MAX([Value])
FOR [Column]
IN ([Money],[Age],[Children])
) as pivotTable


Anyway, the solution I had was to create the necessary table in the code behind add a row for each Name and a column for each of the distinct value of Column, then cycle through the rows of the original table and just place the values in the new table. All the values are present and already ordered so I only need to do it using row and column indexes that are easily computed.

The whole operation lasted 36 seconds. There were many rows and columns, you see. Anyway, I profiled the code, using the great JetBrains dotTrace program, and I noticed that 30 seconds from 36 were used by DataRow.set_Item(int, object)! I remembered then that the DataTable object has two BeginLoadData and EndLoadData methods that disable/enable the checks and constraints in the table. I did that and the operation went from 36 to 27 seconds.

Quite an improvement, but the bottleneck was still in the set_Item setter. So, I thought, what will happen if I don't use a DataTable at all. After all, the end result was being bound to a GridView and it, luckily, knows about object collections. But I was too lazy for that, as there was quite a complicated binding code mess waiting for refactoring. So I just used a List of object arrays instead of the DataTable, then I used DataTable.Rows.Add(object[]) from this intermediary list to the DataTable that I originally wanted to obtain. The time spent on the operation went from... no, wait

The time spent on the operation went from the 27 seconds I had obtained to 5! 5 seconds! Instead of 225.351 calls to DataRow.set_Item, I had 1533 calls to DataRowCollection.Add, from 21 seconds to 175 miliseconds!

Researching the reflected source of System.Data.dll I noticed that the DataRow indexer with an integer index was going through

DataColumn column=_columns[index]; return this[column];

How bad can it get?! I mean, really! There are sites that recommend you find the integer index of table columns and then use them as integer variables. Apparently this is NOT the best practice. Best is to use the DataColumn directly!

So avoid the DataRow setter.

Update July 18, 2013:

Someone requested code, so here is a console application with some inline classes to replace the DataTable in GridView situations:

class Program
{
    static void Main(string[] args)
    {
        fillDataTable(false);
        fillDataTable(true);
        fillDataTableWriter();
        Console.ReadKey();
    }

    private static void fillDataTable(bool loadData)
    {
        var dt = new DataTable();
        dt.Columns.Add("cInt", typeof(int));
        dt.Columns.Add("cString", typeof(string));
        dt.Columns.Add("cBool", typeof(bool));
        dt.Columns.Add("cDateTime", typeof(DateTime));
        if (loadData) dt.BeginLoadData();
        for (var i = 0; i < 100000; i++)
        {
            dt.Rows.Add(dt.NewRow());
        }
        var now = DateTime.Now;
        for (var i = 0; i < 100000; i++)
        {
            dt.Rows[i]["cInt"] = 1;
            dt.Rows[i]["cString"] = "Some string";
            dt.Rows[i]["cBool"] = true;
            dt.Rows[i]["cDateTime"] = now;
        }
        if (loadData) dt.EndLoadData();
        Console.WriteLine("Filling DataTable"+(loadData?" with BeginLoadData/EndLoadData":"")+": "+(DateTime.Now - now).TotalMilliseconds);
    }

    private static void fillDataTableWriter()
    {
        var dt = new DataTableReplacement();
        dt.Columns.Add("cInt", typeof(int));
        dt.Columns.Add("cString", typeof(string));
        dt.Columns.Add("cBool", typeof(bool));
        dt.Columns.Add("cDateTime", typeof(DateTime));
        for (var i = 0; i < 100000; i++)
        {
            dt.Rows.Add(dt.NewRow());
        }
        var now = DateTime.Now;
        for (var i = 0; i < 100000; i++)
        {
            dt.Rows[i]["cInt"] = 1;
            dt.Rows[i]["cString"] = "Some string";
            dt.Rows[i]["cBool"] = true;
            dt.Rows[i]["cDateTime"] = now;
        }
        var fillingTime = (DateTime.Now - now).TotalMilliseconds;
        Console.WriteLine("Filling DataTableReplacement: "+fillingTime);
        now = DateTime.Now;
        var newDataTable = dt.ToDataTable();
        var translatingTime = (DateTime.Now - now).TotalMilliseconds;
        Console.WriteLine("Transforming DataTableReplacement to DataTable: " + translatingTime);
        Console.WriteLine("Total filling and transforming: " + (fillingTime+translatingTime));
    }
}

public class DataTableReplacement : IEnumerable<IEnumerable<object>>
{
    public DataTableReplacement()
    {
        _columns = new DtrColumnCollection();
        _rows = new DtrRowCollection();
    }

    private readonly DtrColumnCollection _columns;
    private readonly DtrRowCollection _rows;

    public DtrColumnCollection Columns
    {
        get { return _columns; }
    }

    public DtrRowCollection Rows { get { return _rows; } }

    public DtrRow NewRow()
    {
        return new DtrRow(this);
    }

    public DataTable ToDataTable()
    {
        var dt = new DataTable();
        dt.BeginLoadData();
        _columns.CreateColumns(dt);
        _rows.CreateRows(dt);
        dt.EndLoadData();
        return dt;
    }

    #region Implementation of IEnumerable

    public IEnumerator<IEnumerable<object>> GetEnumerator()
    {
        foreach (var row in _rows)
        {
            yield return row.ToArray();
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    #endregion
}

public class DtrRowCollection : IEnumerable<DtrRow>
{
    private readonly List<DtrRow> _rows;

    public DtrRowCollection()
    {
        _rows = new List<DtrRow>();
    }

    public void Add(DtrRow newRow)
    {
        _rows.Add(newRow);
    }

    public DtrRow this[int i]
    {
        get { return _rows[i]; }
    }

    public void CreateRows(DataTable dt)
    {
        foreach (var dtrRow in _rows)
        {
            dt.Rows.Add(dtrRow.ToArray());
        }
    }

    #region Implementation of IEnumerable

    public IEnumerator<DtrRow> GetEnumerator()
    {
        return _rows.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    #endregion
}

public class DtrRow
{
    private readonly object[] _arr;
    private readonly DataTableReplacement _dtr;

    public DtrRow(DataTableReplacement dtr)
    {
        _dtr = dtr;
        var columnCount = _dtr.Columns.Count;
        _arr = new object[columnCount];
    }

    public object this[string columnName]
    {
        get
        {
            var index = _dtr.Columns.GetIndex(columnName);
            return _arr[index];
        }
        set
        {
            var index = _dtr.Columns.GetIndex(columnName);
            _arr[index] = value;
        }
    }

    public object this[int columnIndex]
    {
        get
        {
            return _arr[columnIndex];
        }
        set
        {
            _arr[columnIndex] = value;
        }
    }

    public object[] ToArray()
    {
        return _arr;
    }
}

public class DtrColumnCollection
{
    private readonly Dictionary<string, int> _columnIndexes;
    private readonly Dictionary<string, Type> _columnTypes;

    public DtrColumnCollection()
    {
        _columnIndexes = new Dictionary<string, int>();
        _columnTypes = new Dictionary<string, Type>();
    }

    public int Count { get { return _columnIndexes.Count; } }

    public void Add(string columnName, Type columnType)
    {
        var index = _columnIndexes.Count;
        _columnIndexes.Add(columnName, index);
        _columnTypes.Add(columnName, columnType);
    }

    public int GetIndex(string columnName)
    {
        return _columnIndexes[columnName];
    }

    public void CreateColumns(DataTable dt)
    {
        foreach (var pair in _columnTypes)
        {
            dt.Columns.Add(pair.Key, pair.Value);
        }
    }
}


As you can see, there is a DataTableReplacement class which uses three other classes instead of DataColumnCollection, DataRowCollection and DataRow. For this example alone, the DtrRowCollection could have been easily replaced with a List<DtrRow>, but I wanted to allow people to replace DataTable wherever they had written code without any change to the use code.

In the example above, on my computer, it takes 1300 milliseconds to populate the DataTable the old fashioned way, 1000 to populate it with BeginLoadData/EndLoadData, 110 seconds to populate the DataTableReplacement. It takes another 920 seconds to create a new DataTable with the same data (just in case you really need a DataTable), which brings the total time to 1030. So this is the overhead the DataTable brings for simple scenarios such as these.

and has 2 comments

A while ago there was this site called Pandora (similar to lastFM, but better) that tried to match songs based on their internal structure not user preference. By choosing which songs you liked or you didn't like it would guess your preferences and try to play only songs you would listen to.

Apparently Winamp has a little known (or blogged) addin that does this. It is called the Nullsoft Playlist Generator and comes bundled with WinAmp. This is how you use it:
  1. Open Winamp and go to Media Library
  2. Create a playlist (or more) and add all your songs there
  3. Right click on the playlist and select Send To: Add to Local Media
  4. Go to Options, Preferences, Plug-ins, Media Library and click on Nullsoft Playlist Generator
  5. Click on Configure selected plug-in, select your options and click Scan. I recommend the background scanning option.
  6. After the scan is complete (or during it) you can right click on any song and select "Play similar song to..." and you will listen to songs that this software thinks are similar



That's it. The analysis is pretty superficial, but still better than nothing. It is perfect when you have gigs of songs and you don't want to browse forever, selecting which one you want or you don't want.

and has 0 comments
I am obsessed by this song, I am just listening to it again and again, typing at hyperspeed while I am doing it (I wish I would type meaningful things, too :) ). The video itself is from Smack My Bitch Up, but YouTube again blocked a cool clip so I had to take another from some other place. I couldn't find the original video for the song. (One that wasn't a fan made anime clip :-|)

Update: even worse, all video platforms other than Youtube have been sued out of existence and even on YouTube the only versions of this song you find are live concerts. It's amazing: a beloved video of a famous song just vanished off the Internet... If you find it somewhere, please let me know. Meanwhile, this is a remix version...



Usage: Pump up the volume and get in front of a keyboard on monday morning. :)

and has 0 comments

Finally, another book finished. It is not that I am illiterate, really, but lately I have been listening to podcasts every single free minute. I even fall asleep like that sometimes.

Anyway, this book is rather well written and gives some interesting insights into the Microsoft "puzzle" hiring interviews, revealing as well the highly competitive culture behind the system, as well as the most obvious flaws. One of the most famous such puzzles is in the very title of the book. The interviewer would ask one how would they move mount Fuji. The expected answer is a detailed analysis of the process and the more situations and data the candidate thinks of, the better. Of course, there are really stupid puzzles as well, used only to assess how the prospective employee reacts under stress. Others are deceptively simple, but hard to guess.

I will give you one. Please think about it as long as it takes to be CERTAIN the response is right. In fact, I won't even give you the answer. Here it goes:

You have four cards on the table. Each card has a digit on a side and a capital letter on the other. As placed on the table you see the cards like this:

4 G E 3



The request of the puzzle is this: what cards must be turned in order to verify that the four cards on the table verify the rule "Every card with a vowel has an even number on the other side". You need to give the exact cards not the number of cards and (of course) turn only the ones that you need, so as little card turning as possible.

A bit slow on the wagon, but I didn't need this until now. It is all about creating a .NET assembly for use by the SQL Server. These are the quick and dirty steps to it.

C# Steps
1. Create a Class Library project (some links suggest an Sql Server Project, but that is not available for Visual Studio versions below Professional)
2. Add a public class
3. Add a public static method and decorate it with [SqlFunction]
4. Do not use static fields in the said class
Compile the assembly.

SQL Steps
1. Define the assembly in SQL:
CREATE ASSEMBLY MyAssembly FROM 'C:\SqlCLR\MyAssembly.dll'

2. Create the SQL function to use the method in the assembly:
CREATE FUNCTION MyUserDefinedFunction(
@s1 NVARCHAR(4000),@s2 NVARCHAR(4000) ... other parameters )
RETURNS FLOAT AS
EXTERNAL NAME MyAssembly.[MyNamespace.MyClass].MyUserDefinedFunction

3. Enable CLR execution in SQL Server:
EXEC sp_configure 'clr enabled', 1
GO
RECONFIGURE
GO

4. use the function like
SELECT dbo.MyUserDefinedFunction('test','test2'...)


Things to remember:
1. Make sure the parameter types are the same in the .NET method and the SQL function
- the float keyword in SQL means double in .NET! I have no idea what kind of SQL type you must use in your function to match a .NET float.
- the string in .NET is matched to nvarchar in SQL
- the bit is matched to a bool as expected
2. Whenever you change the DLL you must DROP all the functions, then DROP the assembly, then create it again. If there are no signature changes, I guess just replacing the dll file could work.

There are a lot of things to say about returning tables instead of single values or about defining user defined aggregate functions, but not in this post.

and has 0 comments
Long time since I posted a song on the blog. This is one old, but good song AND video. Rarely you find a truly good combination of sound and presentation nowadays. Quoting from the Wikipedia article for this song: Radiohead frontman Thom Yorke wrote the song about a narcissistic friend of his, which on closer inspection is showcased by the imagery in the lyrics - a parallel to earlier My Iron Lung EP track "Lewis [Mistreated]". He also says that it was somewhat of a competition between him and Jonny Greenwood to see who could fit the most chords into a song. "Just" is especially notable for Greenwood's guitar solo, which showcases some of his first uses of the Digitech Whammy Pedal. The guitar work in the song has been seen as an homage to post-punk band Magazine, one of Radiohead's key influences at the time.



The video reminds me of an old sci-fi story I've read about a word that, when heard by a person, would transform them into a purple jelly cone, including the one saying it. When someone finally understood and accepted the reality of it, it all turned into a race to stop a deaf person going to a radio station and speaking the word. He was immune, you see. Anyway, enjoy.

and has 0 comments

Science-fiction author Arthur C. Clarke is one of the people that has defined me as a person and who's books provided both comfort and excitement during my childhood and adolescence. He is mostly known for the movie adaptation of 2001: A Space Odyssey although I liked the Rama series more. He also invented the concept of a geo synchronous satellite. 
He has lived a full life and I don't believe in artificially prolonging living above a certain threshold (he was suffering for 13 years now), so I am just happy to have known about him rather than sad for his death.

More details at this BBC News article and this Wikipedia entry.

and has 0 comments
Ok, I will make a quick list and description. The rest is up to you.
  • Stargate Atlantis - the spinoff series of Stargate SG1 has ended its 4Th season, but a 5Th is under way. I am watching it mechanically now, as the quality and originality of the show has decreased in time to the point of negative values

  • Battlestar Galactica - another sci-fi show, it reinvented completely the story of the old 70's BattleStar Galactica. It started great, but the third season ended in some weird pseudo spiritual mambo jumbo. Hopefully, the fourth season due in April will not suffer from the 'Lost' disease

  • Doctor Who - British sci fi, a bit goofy, but fun nonetheless. It is about an alien that travels space and time with his human female companions (nothing kinky though ;) )

  • Eureka - silly sci-fi show about an American town that is populated only with brilliant scientists. Very far fetched, but nice as a light comedy. I haven't been able to finish season 2 that finished airing. I think there will be a season 3 as well.

  • Regenesis - a bit hard to catalogue, this Canadian sci-fi depicts a multinational scientific group with no political associations trying to fight the medical national emergencies in the world. All kinds of diseases and wacky characters, but a bit failing in the field of science. Season 4 is ongoing.

  • Jericho - now this is a series that was almost cancelled, then brought back at popular demand. Twelve American cities have been blown to smithereens by carefully planted nukes. The US quickly destroyed Iran and North Korea, but it seems the actual perpetrators are American. A small town in the US has to fight off both corporate conspiracies, the newly formed American government and the bands of bandits and neighbouring towns that want what Jericho has: a fan base :).

  • Numb3rs - oh, what a waste. It started so beautifully as a mathematician applying math to help his FBI agent brother. By season 3 it got completely unscientific, season 4 lost math completely and turned into yet another cop show.

  • Lost - I am not watching this anymore, only my wife does. I stopped watching this crap after the first season. Meanwhile they use the same psychological system to carry on a story that makes no sense and that everybody watches for the sole purpose of seeing it end. Like a modern day 1001 Arabian nights played on the audience. The only worth watching part of Lost is the pilot episode, then you should continue the story in your own way.

  • Grey's Anatomy - medical/soap opera. My wife watches it. It started a bit interesting, but ended up crappy. Almost no medicine anymore, instead you see the personal issues of various medical staff people.

  • Private Practice - as if Grey's Anatomy was not enough, they made a spinoff out of it. I don't know if it will ever air again, though, with the writer strike and all.

  • Ugly Betty - it proved a commercial success in Latin America, so the TV corporations cloned it for the US market. A gayified version of the South American show, it is basically a women magazine made TV series.

  • Prison Break - interesting beginning. I recommend the first season, then it all got 'Lost', with psychological effect to keep the audience interested, an escalation of tension, a complete disaster of a plot.

  • House MD - this one lasted a bit longer before turning to shit. It is a medical show that depicts a wacky, but brilliant diagnostician trying to figure out what the disease and cure is before the sick expires. It has become repetitive and self-satirical, moving away from medicine and back on the ugly and not interesting ploy of human relationships, but then it got back on track. Still worth watching, although the quality is dropping and the story grows old.

  • Criminal Minds - TV cop show with a team of FBI agents trying to find criminals by using behavioural analysis. Interesting enough, although, as you can imagine, not very technical.

  • Sarah Connor Chronicles - [chuckle] Terminator is not a teenage girl. She protects John Connor and his mother from other Terminators that roam freely in the past, yet keep a low profile for some reason or another. It's not terrible.

  • South Park - delicious animated gross comedy, making fun of everything and everybody. They lost the way around season 10, when the authors seemed buried in scandals and full of rage, unable to make fun of things, starting to instead vent frustration in the show. I am happy to see they have recovered in season 11 and season 12 has just started.

  • Dexter - a serial killer hunts serial killers. This makes him good, somehow, but he is still a killer. Funny enough his cop father taught him how to hide from the police, his sister doesn't know and she is a cop, too, and a colleague of Dexter, who is a criminal forensic in the police department.

  • Big Love - this is like a family in distress kind of show, but this time the family is made of one husband, 3 wives and numerous children I've lost count of. Yes, they are Mormons and they must navigate the perils of hiding their religion and marital arrangements from the rest of the world, while managing to obey or wriggle around the organisational structure of the Mormons in their community. As much a fascinating subject as this is, the show is pretty ordinary. Tom Hanks is an executive producer.


That's about it.

and has 0 comments
While in search for interesting and high quality podcasts I've stumbled upon escapepod.org, a site that offers free sci-fi stories in audio format. They last about 40 minutes, so just about the time it takes me to get from my home to work and they are great in both content and narration quality. It completely takes care of my needs when I get back home and I don't feel like listening to some tech podcast.

Even more, it seems that they post two or three books a week, so you won't finish the site right away. Great job, guys! A site truly after my own heart: exactly what you need, how you need it and with no annoying ads or marketing ploys.

and has 1 comment
As a software developer with no formal training, I sometimes feel humbled by the more standardised approaches to programming like, for example, Test Driven Development or TDD. But I think that today I finally figured it out.

You see, TDD is supposed to "cover your code" with tests. Once all your tests run without fail, you know that you can focus on other parts of the code, like refactoring, interface or performance improvements or on new features. But what it actually means is a simulation of your client and/or debug person. Once you automatically simulate a client, you can make sure it is satisfied before you move on to the real person. And this is also where the whole thing fails, because it is obviously impossible to simulate a human being without real effort that surpasses the building of the very software you are trying to test. It would be fun to actually do it, then watch the software complain on its own functionality. If any software is going to take over the world, one that emulates an annoying client probably will.

One of the hardest parts to simulate is the work with the interface. No test will ever be able to look disappointed while expressing a lack of enthusiasm on your choice of colors. It is even harder to test web interfaces, although software that can test some of the behaviour of web apps and sites exists, with limited functionality. Also, it is impossible to test for functionality that is not there.

A good use of tests is to address (and in this way document) the bug findings! When you see a bug, you create a test that fails because of it, then you fix the bug. Also, by trying to cover as much of your code with the tests, you get to formalize the access to your code and also are forced to decouple interface from code. No wonder that all the test frameworks are used for Unit Testing. Once you can create a unit or a library of code with no other inputs or outputs than data types, you can test the hell out of it.

But it still leaves the interface out. I have been thinking of ways of describing the test procedure not in code, but in English, something like a unit test for a person rather than a testing framework. This can be further automated, where possible, or just followed by a dedicated tester.

What I would really be interested in would be a general way of creating tests for recurring bugs. A sort of code policy enforcement, if you will, but one that would test for the same bug multiple applications. Can it be done without also formalising the structure of those applications?

A while ago I wrote a quick post to remind me of how to use the AutoCompleteExtender, but recently I realised that it was terribly incomplete (pun not intended). I've updated it, but I also felt that I need to restructure the whole post, so here it is, with more details and more code fun.

First of all, a short disclaimer: I am not familiar with the ASP.Net Ajax javascript paradigm. If some of the things that I am doing seem really stupid, it's because I did it by trial and error, not by understanding why the code is as it is. Here it goes.

There are two ways in which to use the AutoCompleteExtender: using PageMethods or using web service methods. The details are in the previous post, I will only list the gotchas in this one.
  • PageMethods requirements:
    1. ScriptManager must have EnablePageMethods="true"
    2. The page method must have the form public static string[] MethodName(string prefixText, int count) AND THE SAME PARAMETER NAMES. If you change prefixText with text it will not work!
    3. The page method has to be public and STATIC
    4. No, it is not possible to declare the method in a web user control, it must be in the page
  • Web service requirements:
    1. The method must have the form public string[] MethodName(string prefixText, int count) AND THE SAME PARAMETER NAMES. If you change prefixText with text it will not work!
    2. The method has to be public and NOT STATIC
    3. The method must be marked as ScriptMethod
.

Now, the method can return an array different from a string array, but the only useful types there would be numerical or maybe dates. Any object that you send will ultimately be transformed into "[object Object]". There is a way to send a pair of value,text encoded in the strings, and for that you use:
AutoCompleteExtender.CreateAutoCompleteItem(text, value);

It doesn't help much outside the fact that in the client javascript events of the AutoCompleteExtender the first parameter will be the AutoCompleteExtender javascript object and the second an object with a _text and a _value properties.

One of the questions I noticed frequently on the web is: How do I show the user that there are no auto complete matches?. The easy solution is always to return at least one string in the string array that your method is returning. If there are no matches, make sure there is a "No Match" string in the list. But then the complicated part comes along: how do you stop the user from selecting "No Match" from the list? And I do have a solution. It seems that the text in the textbox is set based on the existence of a javascript object called control that has a set_text function. If the object or the function do not exist, then a simple textbox.value=text is performed. So I used this code:

string script = @"var tb=document.getElementById('" + tbAutoComplete.ClientID + @"');if (tb) tb.control={set_text:setText,element:tb};";
ScriptManager.RegisterStartupScript(Page,Page.GetType(),UniqueID+"_init",script,true);
to set the object for my textbox. And also the javascript code that looks liks this:
function setText(input) {
if (input=='No Match') return;
this.element.value=input;
}


These being said, I think that one can use the AutoCompleteExtender and know what the hell is making it not work.

Update: The 30 September 2009 release of the AjaxControlToolkit doesn't have the error that I fix here. My patch was applied in July and from September on the bug is gone in the official release as well. Good riddance! :)

==== Obsolete post follows

I've just downloaded the 29 feb 2008 release of the AjaxControlToolKit and I noticed that the TabContainer bug that I fixed in one of the previous posts did not work anymore. So the post is now updated with the latest fix.

Fixing TabContainer to work with dynamic TabPanels

Apparently, the guys that make the Ajax Control Toolkit are not considering this a bug, since I posted it a long time ago as well as a bunch of other folks and there are also some discussions about it on some forums.

and has 5 comments
Well, imagine a lonely boy, without a family, learning magic in a special school and who's archenemy is a powerful yet evil wizard. He is always accompanied by his friends, a boy and a girl. The evil wizard likes snakes and manages to kill the headmaster of the magic school. No, it's not Harry Potter, it's Naruto!

It's like the Japanese liked Harry Potter, but thought they can do one better. They're not exactly magicians, but ninjas; Naruto Uzumaki, the main character, is a mix of both Harry and Ron, while boy number two, Sasuke Uchiha, is more like a small Snape. With a bit of a stretch, one could take the Naruto story and rip it off in a prequel to Harry Potter, with the parents as the characters :)

Anyway, long story short: the anime is children oriented, with all kind of soapy feelings, camaraderie and friendships, no gore, little blood, a bit of death, but "censored" where violence or tension is concerned. If you ignore the ridiculous simplicity of the characters, the story is pretty captivating and the "ninja science" fun. It more than makes up in quantity what it misses in quality. The first anime, Naruto, is concerned with the childhood of the characters and spans 220 episodes, while the ongoing Naruto: Shippūden with the adolescence and it is close to 50 episodes so far. There are 20 minutes episodes, if you count the 1.5 minutes presentation in, but don't worry, the fights last well into fourth episodes >:). Also, there are currently 4 Naruto movies: 3 for the first series and 1 for Shippūden.

Basically, if you cross Inuyasha with Harry Potter you get Naruto. I guess that any media industry, once it reaches a level of maturity, makes compromises in order to satisfy the greater audience. What Hollywood did for the US, the anime companies are doing for Japan, but in the end, the result is the same: dumbed down versions of what it could be.

Fortunately, animes are often based on manga publications and you can read Naruto well over the story arch in the anime, freely online.

Links:
Naruto Wikipedia
Naruto Manga Online
Naruto meets Harry Potter video

This blog post is about ASP.Net Ajax calls (Update panel and such), if you are interested in aborting jQuery.ajax calls, just call abort() on the ajax return object.

Kamal Balwani asked for my help on the blog chat today and asked for the solution for a really annoying issue. He was opening a window when pressing a button on an ASP.Net page and that window used web services to request data from the server repeatedly. The problem was when the window was closed and FireFox (the error did not appear on Internet Explorer) showed a 'Sys is not defined' error on this javascript line: _this._webRequest.completed(Sys.EventArgs.Empty);.

It was a silly error, really. There was this javascript object Sys.Net.XMLHttpExecutor and it had a function defined called _onReadyStateChange where a completed function received Sys.EventArgs.Empty as an argument. At that time, though, the page was unloaded as well as any objects defined in it. I consider this a FireFox bug, as any javascript function should not try to access an object that was unloaded already.

Anyway, going through the Microsoft Ajax library is a nightmare. I am sure they had clear patterns in mind when they designed it this way but for me it was a long waste of time trying to get my head around it. Finally I've decided that the only solution here was to abort the last Ajax request and so I've reached these two posts:

Cancel a Web Service Call in Asp.net Ajax
How to cancel the call to web service.

Bottom line, you need to use the abort function on a WebRequestExecutor object which one can get from using the get_executor function on a WebRequest object which should be returned by a scriptmethod call.

But you see, when you execute TestService.MyMethod you get no return value. What you need to do is use TestService._staticInstance.MyMethod which returns the WebRequest object required! Good luck figuring that out without Googling for it.

From then on the ride was smooth: add an array of web requests and at the window.onbeforeunloading event, just abort them all.

Here is the code for the popup window:

<body onload = "runMethod();" onbeforeunload = "KillRequests();">

function runMethod() {
   if (!window._webRequests) window._webRequests = Array();
   _webRequests[_webRequests.length]
      = TestService._staticInstance
        .MyMethod(OnSuccess, OnTimeout);
   }


function OnSuccess(result) {
   //do something with the result
   setTimeout(runMethod, 500);
   }


function OnTimeout(result) {
   setTimeout(runMethod, 500);
   }


function KillRequests() {
   if (!window._webRequests) return;
   for (var c = 0; c < window._webRequests.length; c++) {
      if (window._webRequests[c]) {
         var executor = window._webRequests[c].get_executor();
         if (executor.get_started()) executor.abort();
         }
      }
   }