Sunday, October 12, 2008

Code Nuggets: A Side-effect of Using DropDownList AppendDataBoundItems With DataBound Items

Picture this: You have a webform with two DropDownLists, both of them are databound to some data you get from a database. Now the first DropDownList's selection determines the contents of the second dropdown. So you simply do a AutoPostBack = true for the first dropdown and populate the second dropdown in the handler function. Right?

But wait. What if you are required to put in a static item in the dropdown? Something like "-- Please Select --" as the first item in the list to force the user to make a conscious choice. Hmmm, so you look around and find the nice little property named AppendDataBoundItems that will take care of that. All you have to do is declare the first (static) item in the Items collection in the designer (or put a <asp:ListItem> tag inside your <asp:DropDownList> tags) and set AppendDataBoundItems to true. This nice little property tells the DropDownList to add the databound items after the statically declared items, so you can have your happy little "-- Please Select --" in your dropdown.

The Side-effect:

The side-effect becomes evident when you play around with your two dropdowns. Its immediately clear that something is not quite right. The AppendDataBoundItems property forces your dropdown's items from the previous postback to be treated as static objects on this display. Sort of where you get an ever-growing second dropdown with a hangover from the postback, which is clearly not what you wanted in the first place!

The Nugget:

So the quick solution is to use a loop to remove items selectively from your dropdown. Remember you still want to retain your first item, so that's why you use a loop. And a while loop at that.

while (DropDownList1.Items.Count != 1)
{
    DropDownList1.Items.Remove(DropDownList1.Items[1]);
}

There. You won't have a problem with your static-dynamic dropdowns anymore! You can even extend it to other purposes, if you have several static items that you want to preserve, or if you want to preserve static items that are of a particular value. The possibilities are endless, and the pain in your back is gone.

Other Possible Solutions Others Propose:

Some people think that doing a DropDownList1.Items.Clear() would do the trick, but it doesn't. Remember, you want to retain your first object. Or if you want to add your first (static!) object manually again then perhaps you can do that.

Yet others propose a rather swashbuckling DropDownList1.EnableViewState = false, do this only at your own risk and if you are sure that your user would never have to land on this page again during the current flow of your application (of course for which you cannot be sure, what if there is a network timeout?).

A Note:

Perhaps you'd want to use a for loop in place of that while loop, trying to do a quick

for (int i = 0; i < DropDownList1.Items.Count; i++)
{
    DropDownList1.Items.RemoveAt(i);
}

but believe me, it wouldn't work. Why? Because the DropDownList shrinks as you remove items from it, so your loop is bound to fail at some point, terminating earlier than it should. And of course I don't have to remind anyone that you cannot remove items from a collection while using an Iterator.

So that's it, I think the nugget had pretty much sauce alongside it!

(You can get a low-down on AppendDataBoundItems on ScottGu's blog or Andrew Rea's blog)

Sunday, September 28, 2008

Code Nuggets: Getting two SQL column values in a single column

Well this type of thing doesn't come up very frequently (at least to me) and if you're like me working on multiple databases it gets very frustrating when it does come up. Since I don't use it very frequently, I tend to forget how to do it properly in the database system I am using at the time.

So it goes something like this: Suppose you have a simple SQL table called Users. Now this table has three columns, id (int), firstName (varchar) and lastName (varchar). Sometimes you have to return the full name from the database in a single column (for reasons of sanity, or otherwise). How do you do it depends on your DBMS. (We assume that we have a record (1, 'George', 'Lucas') in the table.)

MySQL:

MySQL supports it via the CONCAT function. You can have as many values as you want as the parameters to the function.

Example:
SELECT CONCAT(firstName, LastName) from Users

would return:
GeorgeLucas

and would even be better if you use a CONCAT(firstName, " ", LastName) in its place which would give you a nice space in between the names.

Oracle:

Oracle also supports the CONCAT function, but you are restricted to only two values as parameters. However you can CONCAT the CONCAT function itself on the cost of getting your code ugly. Another way of concatenating multiple strings in Oracle is actually using the || operators.

Example:
SELECT CONCAT(firstName, CONCAT(" ", lastName)) from Users

or

SELECT firstName || " " || lastName from Users

both accomplish the same thing and would return:

George Lucas

SQL Server:

With SQL Server it actually gets a little bit easier if you are used to concatenate your strings through the '+' operator. However make sure that you CAST any numeric values to varchar before trying to concatenate it, as '+' also works as the addition operator.

Example:
SELECT firstName + " " + lastName from Users

That's all to it to the concatenation function, and remember that selecting two values and displaying them as a single values is also called concatenation (a thing that I usually look over).

Wednesday, September 03, 2008

java.CompilerError when running RMIC

The other day I was trying out a Java RMI program in connection to an assignment. Let me be very clear here: I really like Java as it was one of my first proper programming languages (mind you, I am talking here circa 1999-2000 when Java-fever hadn't caught up) and I am a big fan of its elegance. The only turn-off which made me head towards Microsoft's direction was the lack of a proper, Visual Studio-league IDE for Java in those days. Much water has passed under the bridge, and there are many better IDEs for Java now, like Eclipse and NetBeans, but the curse still remains. (You might also want to give JCreator a shot, one of my favorite Java editing tools)

So back to where I was, trying RMI. I made a simple interface class, which compiled fine, and then an implementation class, which compiled fine in itself too. Then I had to run RMIC on one of the classes (which I tried doing from command line, since I am not sure how NetBeans handles it), and plop, I got a java.CompilerError stating that something has gone horribly wrong and the compiler is now mangled, and that I am supposed to file a bug report. Something like this (extra line-breaks have been added for readability):

error: An error has occurred in the compiler; 
please file a bug report (http://java.sun.com/cgi-bin/bugreport.cgi).
1 error
----------log:rmic(7/491)----------
sun.tools.java.CompilerError: mangle NItem1Impl     javasoft$sqe$tests$api$java$rmi$Naming$NItem2Impl     javasoft$sqe$tests$api$java$rmi$Naming$NItem3Impl     javasoft$sqe$tests$api$java$rmi$Naming$NItem4Impl
at sun.tools.java.Type.mangleInnerType(Type.java)
at sun.tools.java.Type.tClass(Type.java)
at sun.tools.java.ClassDeclaration.(ClassDeclaration.java)
at sun.rmi.rmic.Main.doCompile(Main.java)
at sun.rmi.rmic.Main.compile(Main.java)
at sun.rmi.rmic.Main.main(Main.java)

Undaunted, I ran a Google search for the error which lead me to this bug report. Mind you, there is no solution in there. I figured the solution out myself. You just have to make sure that the jdk/bin directory is in your PATH variable (I am talking about Windows), and then compile the class from the command line from the class's directory. For example, earlier I was trying to run:
C:\Sun\SDK\jdk\bin>rmic 
"C:\Documents and Settings\uxuf\RMITest\build\RMIImpl"
but this threw an error everytime, so after setting the path variable (through System Properties->Advanced->Environment Variables) I found out that I had to pass the parameter to rmic without the quotes, which automatically means without any spaces :) and became something like:
C:\Documents and Settings\uxuf\RMITest\build>rmic RMIImpl
So if you are stuck in a similar situation, when no solution to that stupid error is in sight, try out rmic from the directory which contains the class. It worked for me!

Sunday, April 20, 2008

The Apple Software Update

With all the talk about Apple apparently forcing Safari on unsuspecting users through the Apple Software Update, I wanted to get a piece of it too. Apple Software Update is usually installed if any software from Apple is installed on your computer, like iTunes or QuickTime. I had iTunes installed on my system as I found it quite convenient to use my iPod with, and since then it (iTunes) has become my de facto audio player.

So I fired up Apple Software Update, and voila! There was no Safari in the list, let alone being checked by default. There was an update to Apple Software Update though, and an update to Apple QuickTime + iTunes. So I randomly updated Apple Software Update to the latest version, and when the update completed, there I had little Safari sitting innocently on my list checked already :)

Moral of the story: Update your Software Update before quipping on Apple.

Epilogue: I might give Safari a spin, because I had played a bit with it when the public beta came out last year. But I am not terribly impressed, not much to ditch my existing Firefox 3 Beta 5, which itself is light years fast of Firefox 2.

Monday, March 31, 2008

PHP: Getting your user's IP Address

It's easy, just use $SERVER['REMOTE_ADDR']. Echoing the user's IP address would look something like this:

echo "IP Address: " . $SERVER['REMOTE_ADDR'];
But that works only in PHP versions greater than 4.1.0. If you're still using earlier versions, use HTTP_SERVER_VARS, and for heavens' sake, upgrade.

Source: PHP: Predefined Variables - Manual (This page should be on the thumbs of all PHP developers)