Thursday, August 30, 2007

PNG Transparency in Internet Explorer 6

In Internet Explorer 6, the background of transparent PNG files shows up as gray instead of transparent. More modern browsers such as Internet Explorer 7, Firefox, and just about every other browser support transparency for PNG files. However with about 30-50% of people still using Internet Explorer 6, many developers still need to have backwards compatibility with IE6.

Even though IE6 does not support transparent PNG it does have a workaround by using the AlphaImageLoader filter. The AlphaImageLoader is part of a collection of filters that are Internet Explorer specific. I do find it odd that the alpha loader is not enabled for all png files because many workarounds use the filter on all PNG images regardless.

A filter is a cascading style sheet property that works with Internet Explorer 5.5 and beyond. I've seen a couple of different implementations of this workaround but the one that I have found to work the best is PNG Behavior from WebFX. A SugarCRM based website that I worked on used this workaround and it worked out quite well.

Basically this workaround uses yet another Internet Explorer specific feature known as behaviors. Behaviors have never really caught on which is a good thing in my opinion because it is an Internet Explorer specific feature so it does not play nice with other browsers and playing nice is important to me. However behaviors can occasionally be used to patch Internet Explorer so it behaves more like other browsers. A behavior is also a CSS property that among other things allows you to attach a JavaScript function to property change events. This property change event can attach the AlphaImageLoader filter to just the img tags that have src attribute as a png file by using JavaScript to do more advanced things than you could do with CSS alone. For all of the details see WebFX's PNG Behavior. One thing to note is that you will need to set the height and width of all image that are png files or the image will not show when using this technique.

The one difference that I have added was a conditional comment that makes it so that this style would only get applied in IE 6

<!--[if IE 6]>
<style type="text/css">
img, .png_input_image_button {
   behavior: url("pngbehavior.htc");
}
</style>
<![endif]-->

You can also attach this style to input image buttons or any other html tag that use src as the attribute for its image.

Saturday, August 25, 2007

JetBrains Resharper review

After having seen many people mentioning JetBrains Resharper I decided to give it a spin.
Some of the features that interested me the most were:

Code Analysis for C#
* Code Suggestions
* Quick-Fixes

Code Refactoring
* It has several refactoring that Visual Studio doesn't have

Code Formating
* Syntax Highlighting
* Namespace Import Directives Optimization - This feature highlights and allows you to remove unused imports
* Automatic Member Layout - Basically code sorting. I've always wanted this feature because if you not careful code gets put in the random order you created it by just adding methods to the end of a class. I love Lutz Roeder's .NET Reflector because it actually puts code in an easy to find order.

However, my trial of Resharper did not last long because it was very slow so I had to uninstall it. The uninstall experience was also not very good either because it did not restore the intellisense settings back to their defaults. I had to reset the Visual Studio settings in order to get that back.

Tuesday, August 21, 2007

Check to see if the ASP.Net session is available

HttpContext.Current.Session will return null when the session information is not available yet while HttpApplication.Session will throw an exception.

It is not uncommon to handle page errors in a Global.asax file's Application_Error event to log and notify administrators of problems with a website that were not handle. This can be used in conjunction with a custom error section of a webconfig to have a more graceful error handling as customErrors turned off is not user friendly and can often lead to security vulnerabilities.

Example:
<customErrors mode="RemoteOnly" defaultRedirect="/Error.htm">
</customErrors>

In my Application_Error I wanted to email the equivalent of the trace's debug information which includes the session information. At first I was using the HttpApplication.Session (this.Session) property of the Global.asax class. However, that are errors (such as a 404 error) where the session is not available yet as the HttpApplication.Session will throw an exception when you try to access it. I didn't have anything that I could do with the exception so I just caught it.

I wanted to find out if there was a way to check whether the session was active so I did have to catch the exception and found out HttpContext.Current.Session returns null. I could check for null instead of catching an exception which is generally considered a better practice.

Regular expression for range of IP addresses

I have several Google Analytics accounts where I wanted to exclude internal traffic for. After checking some popular regular expression libraries such as regexlib.com and not coming up with anything I liked, I came up with the regular expression by hand. However, I didn't realize that on the helpful link of Google Analytics to "How can I exclude my internal traffic from my reports?", a very easy to use JavaScript IP address range generator, that would be helpful anytime you needed to do an IP address range check.

Sunday, August 19, 2007

Programmatically trigger JavaScript debugger

Debugging JavaScript is not always a fun experience. I recently found a new technique for debugging JavaScipt and while writing this blog entry I was reminded of an better technique. The new technique is the using "debugger" keyword. Just by putting this keyword, not a function, on a new line will call the debugger in IE. Firebug also supports the debugger keyword for debugging in Firefox although you don't really need it as much because of its excellent breakpoint support. The debugger keyword has actually been around for a while I just never knew about it. I found it because I was looking to see if there way to programmatically trigger JavaScript debugger like there the way in C# call Debugger.Break().

example:
function foo()
{
    // Triggers the debugger
    debugger

    /* code that I want to debug */

    // These are some ways that I used in the past to trigger the JavaScript debugger
    a.a = 1; // use of undefined variable triggers the debugger
    bar(); // use of undefined function triggers the debugger
}

The technique that I was reminded of was using the "Script Explorer". This window shows all of the script that is currently loaded into the browser. As easy way to to this is by using the IE View menu > Script Debugger > Open. It is not shown by default even when you are debugging JavaScript but you can access it from the Debug menu > Windows > Script Explorer. Although, Visual Studio 2008 has a new Script Document section of the Solution Explorer that replaces Script Explorer.

If you are an ASP.Net developer you may be addicted to the managed code debugger mainly because it just comes up when you need it.

However debugging JavaScript is a different. First, you have JavaScript debugging turned on through IE's advanced options. This is turned off by default which is a good thing - do you remember how annoying it was when it was the default. What's the problem here? It debugs all websites not just the one you are working on. I haven't hear of a way to just debug the website that is loaded into Visual Studio. If you have JavaScript errors turned off then it is easy to ignore the mounting errors. Considering that both Visual Studio and Internet Explorer are both Microsoft products you think that there would be seamless way to configure IE to debug JavaScript.

As even Scott Gu from Microsoft says "One of the annoying things with VS 2005 is that you have to first run your ASP.Net pages before you can set JavaScript breakpoints in them in the debugger." I have found a much better overall user experience from the most excellent Firefox FireBug extension which it is very easy to set and debug JavaScript right from the browser.

Friday, August 17, 2007

Can't create a CNAME record for the root record?

I was trying to create a CNAME record for daveparslow.com that points to the Google Blogger hosting service ghs.google.com but I found out that you can't do that. You can only have an A record for your root website. At first I thought I just didn't understand the process or format to enter the CNAME record. Then after a friend recommended that I switch to www.EveryDns.net as a free place to host dns, I tried to add the CNAME record for the root website and got the following error message:

please use an A record instead -- the delegation records for "daveparslow.com" interfere with the use of a CNAME (rfc1034 section 3.6.2)

I turns out that you can't add a CNAME record because of an RFC. I guess I will have to use a website hosting service to do a permanent redirect to www.daveparslow.com.

Thursday, August 16, 2007

ASP.Net Trace stops showing up

I've noticed that when using asp.net 2.0 dev server that the trace would only show up on one or two pages. I decided to do some research into it and found out it has to do with the trace section of webconfig. There is a attribute called requestLimit whose limit was set to 20. After 20 requests the trace just stops showing up. 20 requests may not sound that bad but with the dev server all requests (including images and everything) go through the asp.net runtime so one page with my website would have 20 requests for other resources. I found out that there is another attribute called mostRecent which when set to true will discard older requests rather than stop working. I also didn't read the note in the webconfig about "you can view the application trace log by browsing the "trace.axd" page from your web application root".

Tuesday, August 14, 2007

ASP.Net TreeView doesn't have AutoPostback

I have a TreeView ASP.Net control where clicking the node would go to the DetailsView while the checkbox represented an action/state of that node. I wanted the check action to happen immediately like you can do with a normal CheckBox, however the ASP.NET TreeView is optimized so it actually does not even have even have child controls but instead "renders" as a single control. In other words it does not generate an ASP.NET CheckBox as a child control instead it renders the markup for an input type="checkbox".

So it seems like there is no possible modify the TreeView to add checkbox autopostback behaviors without redoing the whole control.

It would be nice if the TreeView had a templated TreeNode but that would be a huge departure from the current behavior.

Also on my list of nice things to have for the TreeView would be: Reordering and Popup menu behaviors like MS Live Hotmail's folder features.

As a workaround, I suppose I drop the NavigateUrl that goes to the DetailsView page and use the a blank SelectAction which does cause a postback to check the checkbox and perform the action.

Assigning a value to an ASP.Net CheckBox

Unlike the html checkbox, the ASP.Net CheckBox control does not have a value property. However, you can add attributes via markup as well as pragmatically via code.

Markup:
<asp:checkbox id="CheckBox1" runat="server" value="'<%# Eval("ValueColumn") >' />
<asp:checkbox id="CheckBox2" runat="server" value="'2'">

Only Eval can be used to bind to "custom" attributes, as compared to properties built into the control which also work with Bind

Code:
CheckBox2.Attributes.Add("Value", 2);
The "Add" method add takes two parameters. The first parameter is the name of the attribute . The second parameter is the value for this attribute.

This adds a server accessible attribute for the value, the attributes collection is maintained via the viewstate. However the CheckBox control does not render the value attributed (it actually removes the attribute during the render event phase.

However, if you want to add the attribute so it is rendered via html then the checkbox has a property called InputAttributes, adding properties to this collection will always be rendered in the html.

Code:
CheckBox2.InputAttributes.Add("Value", 2);