Saturday, May 31, 2008

Table-less forms

Often, web designers create (X)HTML forms using tables. Tables tend to clutter up the code when used excessively and ought to be replaced with DIVs coupled with some CSS.

A common issue with creating forms is that the label of the input element varies in width and therefore does not play nicely with respect to alignment (...which is the reason why most people resort to tables). The solution to this problem is to set a width for the label tag. Setting a normal width CSS attribute will not work because a label tag is, by default, an in-line display tag so you have to override the display property with a value of block or set the float property (Set the float property! You'll probably prefer this over setting the display property.).

If you set a uniform width for all form labels, you'll notice that all your input elements are left-aligned. For controls that do not have any label text, you would still probably want to place an empty label tag to get the left-alignment.

Anyway, more from me later. Happy web designing!

PS: For more info, see http://old.macedition.com/cb/testers/icabcss1.html

Wednesday, May 28, 2008

Invisible by style and invisible by attribute

For web page elements, when you set the display style attribute to none, the element is no longer on the screen. What you need to realise is that this is purely due to client side rendering from the browser - the elements are still send from the server to the client and has to be parsed by the browser.

For ASP.NET server side tags, setting the Visible attribute to false prevents the tag from being rendered into the (X)HTML generated for the page. The element never gets transmitted over the network, thus saving bandwidth.

When you're writing Javascript to turn items visible and invisible, you would still set the display style attribute because the element would have to be accessible from the client-side Javascript.

Basically, what this means is that if you're hiding an element to keep it from being used entirely (perhaps due to the user's role or something similar), set the Visible attribute to false and if you're just setting something hidden temporarily, use the display style attribute instead.

Sunday, May 25, 2008

My 'XP' with Windows 2008

I installed Windows 2008 Server on my PC last night. It took a bit of configuring before it would run because Microsoft got a little too paranoid when building this version of Winows. The first thing I did was enable the Desktop Experience feature and then startup the Theme service, which provides the Vista look and feel to the environment (after Personalizing the desktop to set the theme and the appearance). I then had to get the wireless working and although the wireless adapter shows up as a network device, it doesn't detect any networks till you actually enable the Wireless LAN feature - yes, that's right, for the uninitiated, troubleshooting the lack of wireless connectivity can be very frustrating. Lucky for me, it was Google to the rescue. Anyway, I then got rid of the Internet Explorer Security Configuration from the Server Manager in the security section and installed the rest of the drivers for my Lenovo 3000 N100 notebook PC and I was off.

My experience with Windows 2008 has been good so far and there aren't any major setbacks to adopting Windows 2008 as my full-time OS. I guess I'll have to use it for a few weeks before I can form an opinion about it.

Friday, May 23, 2008

Divs or Tables

It has often been suggested that we use divs for layout of items instead of tables in HTML. Normally, the divs would be fine but when it comes to setting the background for the 'columns' created by divs, you would realise that the divs aren't the same size. This is due to the fact that, unlike table cells, divs do not change their height to match horizontally neighbouring divs. The workaround to the issue involves creating a wrapper div and setting the background color in the wrapper and setting a transparent background for the actual column. This creates just as much clutter as a table so everyone in the web design and development world hope CSS3 changes things for the better.

Thursday, May 22, 2008

Exception thrown on calling Response.Redirect

Calling Response.Redirect in a Try-Catch block throws a ThreadAbortException. This is by design - a Response.Redirect internally calls Response.End and this throws a ThreadAbortException. You can create a catch handler that catches only the ThreadAbortException, but catching an exception each time would cause a performance overhead. An alternative would be to call the Response.Redirect overload that accepts a boolean value as a second parameter - pass a false to prevent throwing of the ThreadAbortException.

Publishing a Web application project

When publishing a web application project, you'll have to make sure all of your ASPX (and Master, Controls, ...) use the CodeBehind attribute instead of the CodeFile attribute to reference the CS/VB files. Apparently, Visual Studio doesn't compile into the DLL the code files that are referenced with the CodeFile attribute while publishing. It's just one of the remnants of migrating one of my projects from a web site to a web application project.

Tuesday, May 20, 2008

Using asp:Localize within Javascript strings

A common requirement is to customize the strings displayed in Javascript alert and confirm boxes, such as when providing a multilingual user interface for a web application.

Most developers would use the asp:Localize for this purpose and the problem associated with it is when a single quote is used within the resource file and it gets inserted by ASP.NET into the Javascript string declaration or assignment... it makes the Javascript go haywire due to the appearance of a string terminator within the string literal.

A workaround to this issue would be to create an asp:HiddenField control on the page that reads from the resource file for it's value - our Javascript then gets the control using a $get with a ControlName.ClientID and accessing the value property. Although it's a little more work than using the asp:Localize control within the Javascript string directly, it's a more robust approach.

Sunday, May 18, 2008

Hyperlink column in GridView doesn't like colon

I was building a table using the GridView control to display the names and email addresses out of a datatable that I constructed in the codebehind from an object array returned by the business layer of our 3-tier application. All went well till the part of adding a mailto hyperlink for the email. It took me a while to figure out that the hyperlink column doesn't take a colon for the NavigateUrlFormatString, so that took quite a bit of time figuring out. Unlike PHP, there are some places in code where ASP.NET can perform substitution while in other parts it treats it as a string literal, or worse yet, a malformed server tag. These errors don't show up at compile time so it's time consuming to start the application, log in and navigate to the desired page. I so wish I was on the JavaEE bandwagon right now with some sort of automated testing tool.

Thursday, May 15, 2008

CodeFile and CodeBehind

When developing web sites (no project file), Visual Studio adds the CodeFile attribute to associate the aspx page with the corresponding cs or vb file. Web application projects use the CodeBehind attribute instead. It's just one of those things to watch out for when migrating your ASP.NET web site project to an ASP.NET web application project.

Wednesday, May 14, 2008

ASP.NET: Sequence Numbers in Data Controls

I came across a requirement to build a bunch of tables with a sequence number as one of the columns of the table. Normally, I would create an ASP.NET table and populate the table through code. However, it can turn in a maintenance nightmare if I ever have to change the code. I looked up the issue on Google, since sequence numbers aren't all that uncommon and found a pretty simple solution. In the item template, all we need to do is bind to "Container.DataItemIndex + 1" and that gives the sequence numbers! That's yet another feature that many developers out there who are starting off with ASP.NET do not know about yet.

Tuesday, May 13, 2008

Static Classes in C#

When you create methods that do not require access to any instance variables, you would turn it into a static method. If you've got a class with only static methods, it would be easier for other developers to tell right away that the class was never meant to be instantiated - this is done by marking the class as static. Static classes cannot have a non-static constructor and cannot contain any non-static methods. They are also sealed (implicitly) and therefore cannot be inherited.

An alternative to using static classes is to create a private constructor, although this doesn't prevent you from declaring non-static methods with the class.

Monday, May 12, 2008

LLBLGen Pro - an ORM

Many software projects aim at reducing cost and an Object Relational Mapping tool is one way to cut down development time and the number of developers required. It helps build the data access layer (thinking in terms of the 3 tier architecture with the system divided into the presentation, business and data access layer).

Hibernate (and NHibernate for Java) have been in the limelight a lot due to their open-source nature. I decided to give a commercial ORM a try, which is how I ended up using LLBLGen Pro. It's a code generator with a couple of proprietary libraries and it simplifies access to the database to the extent that you don't have to write any SQL! Using the generated classes is way more simpler than trying to create a database connection and execute commands on the database - with LLBLGen Pro, everything is a method call, whether it is a table, a view or a stored procedure.

LLBLGen Pro supports two primary templates for code generation - the adapter template and the self-servicing template. The adapter template generates classes that separate the entity classes from the persistence logic, much like a DataSet is separated from the DataAdapter. The self-servicing template generates entity classes that handle their own persistence. The self-servicing classes also handle lazy-loading, which is the ability to retrieve data from the database only when you require it; the adapter classes support what is known as a prefetch path that is used instead of lazy loading and is preferred when working in a disconnected mode.

The use of the ORM can lead to a bit of a performance overhead due to the way the generated classes operate. When it comes down to raw performance, hand-written code performs way better than the ORM generated code.