Tuesday, December 11, 2007

Visual Studio 2008 Setup Hangs @ .NET Framework 3.5

On two seperate Vista boxes (the most recent being a fresh install of Vista), the Visual Studio 2008 installation hangs during the "Microsoft .NET Framework v3.5" component.

In both cases, I was able to install the component by removing the following updates:
- Hotfix for Microsoft Windows (KB110806)
- Hotfix for Microsoft Windows (KB930264)
- Hotfix for Microsoft Windows (KB929300)

Friday, November 30, 2007

Fixing the window resize event in IE

Anyone who has hooked into the resize event of the window object in Internet Explorer knows the pain - the event is fired twice for every single movement (once for horizontal and once for vertical).  To make matters worse, if you drag the window size it doesn't get fried twice at the end, it gets fired numerous times throughout the resize.  The result of this is that if you are hooked into the event and are resizing some other elements (and probably re-rendering them too), performance suffers and the page seems unresponsive.

Luckily there is a relatively straight-forward resolution to this:

Sys.Application.add_load(function(sender, args) {
    $addHandler(window, 'resize', window_resize);
});

var resizeTimeoutId;

function window_resize(e) {
     window.clearTimeout(resizeTimeoutId);
     resizeTimeoutId = window.setTimeout('doResizeCode();', 10);
}

Essentially you queue up the resize handling code, and then if the window resize occurs again, you cancel it, and re-queue it.  This keeps happening until the resize is complete, at which point, your doResizeCode() function is actually executed.

Recursively finding controls - where to start?

I love hearing about bugs and problems in components I have authored.  Most people hate hearing about bugs (I assume because they like to think they are perfect), but I like it because it lets me know that people are actually using components I have written, which is always rewarding to know.

I had a report on the CodeProject in response to the article I authored, Persisting the Scroll Position of child DIV's using MS AJAX about a client-side InvalidOperationException during page initialization.   The particular user was embedding my control in a user-control placing two of the controls on the page.  Because my control is an "extender"-type control, one of its properties is the control ID of the other control.  I then use a recursive FindControl method to locate the desired control:

protected virtual Control FindControlRecursive(Control root, string id)
        {
            if(root.ID == id)
            {
                return root;
            }

            foreach(Control c in root.Controls)
            {
                Control t = FindControlRecursive(c, id);
                if(t != null)
                {
                    return t;
                }
            }

            return null;
        }

 

The call to FindControlRecursive looks like:

protected internal Control Control
        {
            get
            {
                if(_control == null)
                {
                    Page page = Page;
                    if(page == null)
                        throw new InvalidOperationException("Page cannot be null");

                    _control = (Control)FindControlRecursive(Page, ControlToPersist);
                    if(_control == null)
                        throw new InvalidOperationException("Could not located the specified control");
                }

                return _control;
            }
        }

Both DIV's in the user-control were named "div1" - can you spot the problem?

_control = (Control)FindControlRecursive(Page, ControlToPersist);

How about now? The problem was I was starting to scan from the Page and all of its children controls - since both DIV's were named "div1", it was always picking up the first control! To resolve this issue I changed Page to Parent:

_control = (Control)FindControlRecursive(Parent, ControlToPersist);

In this case, the Parent is the web-control (or page) hosting the extender control. Lesson Learned: Always start scanning controls from your parent control, not anything higher up in the chain.

Monday, November 26, 2007

Don't store request variables in the ViewState!

I've been mucking around with (D)LINQ all week (this will probably be its own series of posts if I get around to it) and as a part of this, I've been reading a lot of blogs (no-thanks to Microsoft's lack of implementation demos).  Something I've noticed in a few entries is storing a variable available in the Requests body in the pages ViewState.

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            if (!string.IsNullOrEmpty(Request["id"]))
                Id = Convert.ToInt32(Request["Id"]);
        }
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        Controls.Add(new LiteralControl(string.Format("Id is {0}", Id)));
    }

    protected int Id
    {
        get
        {
            object o = ViewState["Id"];

            return (o == null ? -1 : (int)o);
        }
        set { ViewState["Id"] = value; }
    }
}

I can think of a few reasons why this is unnecessary:

  1. During any ASP.NET client-server interaction on this page, the exact URL will be used hence the data will always be available in the HttpRequest object
  2. Adds to viewstate (obviously) = increased transit size and time-to-serve
  3. Serialization/deserialization on every hit

Since it's available on every request, don't bother yourself with the viewstate, save a few lines of code and just grab it from the Request during the pages Load event:

public partial class _Default : System.Web.UI.Page
{
    int Id;

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!string.IsNullOrEmpty(Request["id"]))
            Id = Convert.ToInt32(Request["Id"]);

        if (!Page.IsPostBack)
        {
           // Do stuff...
        }
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        Controls.Add(new LiteralControl(string.Format("Id is {0}", Id)));
    }   
}

As an added bonus, the HttpRequest is available much earlier in the page lifecycle (before the viewstate) permitting initial events access to this (you would of course need to parse it much earlier too).

Monday, November 19, 2007

Apple Warranty's aren't so hot

I feel like every time I open my mouth about Apple something negative comes out. I try to be positive, I really do, but the reality is that experience after experience, I just don't have anything good today.

I came into my office today to find my MacBook revving its fan's at high speed displaying a folder with a question mark.  Rebooting only yielded a "click-click-click," classic HD failure symptom. Luckily nothing is important on this machine.  This raises the first myth I'd like to dispel: "Apple hardware is of higher quality than others."  FALSE! The truth is, Apple, Dell, HP, Lenovo, etc., all use pretty much the same hardware.  At the end of the day, they all have Intel processors, ATI/NVidia/Intel video cards, and Maxtor/Segate/WD hard drives, and they all share the same failure rates.

I was actually somewhat excited about this failure as it'd let me test Apple's support first hand.

My initial call was answered by a routing agent within a few rings, but upon routing, I waited on hold for 20 minutes.  I rarely wait more then 5 minutes with Dell.  Upon reaching a tech, I was asked for my first name, phone number, and serial number.  I was advised that I have a 1yr hardware warranty and that my 90 phone support warrantee had expired. "It's definitely a hardware issue," I said.  The Apple rep kindly replied "OK, well what I can do then is start a support incident [requiring your credit card], and if it turns out to be hardware, we'll refund your money."  I then asked what the next step would be and it turned out that for MacBooks, Apple does not offer advanced replacements or on-site technicians, rather you have to take it to an authorized depot.  This regardless of warranty type.

My experience at the depot (MIAD) wasn't much better - A tech came to take my computer, but upon trying to enter in the information into his system, he was unable to do so because of a system problem.  I waited for 20 minutes only to be told that "we'll enter it in later and send you the info."  Not wanted to leave my laptop without any type of receipt, I had the tech write down all his info on a business card. I'm told I they will have a part within 24-72 hours, and fixed within 48 hours after that, depending on their volume (ie: it could be longer).

So all in all, I'm not overly impressed.  Just for the sake of it, let's take a look at a "standard" warranty on a MacBook Pro versus a Dell Latitude:

Standard Features Dell Latitude Apple MacBook Pro
Phone Support Lifetime 90 days
Hardware Warranty 3yrs 1yr
Hardware Replacement Next Business Day advanced swap, 4hr and 2yr available 24-72 hours for parts + 24-72 hours for replacement, return to depot, no advanced swap available
Onsite Technician For parts deemed not "customer replaceable units" (CRU) Not offered

Wednesday, November 14, 2007

MS AJAX Sys.UI.DomEvent documentation missing keyCode property

If you've ever reviewed the JavaScript source code for some MS AJAX-based components like the AJAX Control Toolkit, you might have noticed the use of the Sys.UI.DomEvent.keyCode property in a number of places to handle keyboard input in controls.  I had recalled that there was also a charCode property on the same class, so interested in what the difference was, I headed over to http://asp.net/AJAX/Documentation/Live/ClientReference/Sys.UI/DomEventClass/default.aspx to take a look at the official documentation, but to my surprise, there was no keyCode property listed.

My initial reaction was that this was either an internal field or something that had been deprecated in the RTM, yet there are references to it in the target property too.  What I ultimately discovered is that this is a simple omission in the documentation.

Now back to why I was looking it up in the first place - what exactly is the difference between charCode and keyCode? Patrick Long has a blog entry at http://blogs.charteris.com/blogs/patl/archive/2007/07/04/keycodes-charcodes-and-asp-net-ajax.aspx that sums it all up nicely; charCode will return a value related to the character being pressed whereas keyCode is related to the key being pressed.  For example, 7 on the number pad and 7 on the QWERTY pad will return different keyCode values but the same charCode values.

Tuesday, November 13, 2007

Widescreen resolutions & DVI

One of our helpdesk reps reported an odd problem trying to setup a local workstation with 2 widescreens - when running in DVI, he couldn't get the horizontal resolution any higher then 1280 even though the monitor is optimized for 1400x900.

We're all used to fiddling with video card drivers to resolve these types of issues, but this one was a bit different because it required a monitor driver (when was the last time you had to install one of those?).  Slight side note, but generally speaking you should install the monitor driver because it usually ships with an color profile for the monitor which helps with replicating color consistently.

Before I attempted to install the driver for our Acer 1916W's, I figured I'd take a look at the drivers INF file to see if there was anything of interest to help resolve this issue, and sure enough, there was.

[DEL_CURRENT_REG]
HKR,MODES
HKR,,MaxResolution

[1280]
HKR,,MaxResolution,,"1440,900"

[AL1916W.AddReg]
HKR,"MODES\1440,900",Mode1,,"30.0-82.0,56.0-76.0,+,+"

The interesting line of course is the one proceeding [AL1916W.AddReg].  HKR is an identifier for "relative root", which in the case of the Acer driver is HKLM\System\CurrentControlSet\Control\Class\{4D36E96E-E325-11CE-BFC1-08002BE10318}\XXXX\MODES (the GUID is found at the ClassGuid property of the INF file).  You can see that the INF is adding in the supported resolution to the Modes key, allowing us to choose the correct resolution now!

Tuesday, November 06, 2007

Windows Live Writer is Here!

Finally, a Microsoft Blog publishing tool that works!

I have been trying to get Microsoft Word 2007 to talk with Blogger for some time now to no avail and to further frustrate matters, the beta versions of Windows Live Writer would not install on x64, but that has all changed now.

Microsoft has just released Windows Live Writer, and keeping up with everything else coming out of the Live BU lately, it seems just great!

If you're interested in trying Windows Live Writer, along with the rest of the Live software packages (Messenger, Photo Gallery, etc), you can grab them at http://www.windowslive.com/.

Monday, November 05, 2007

Paul Thurrott's "Inside Windows Server 2008"

Paul Thurrott has an interesting article on how Windows Server 2008 was developed - a short but recommended read: http://www.winsupersite.com/showcase/win2008_inside.asp

Thursday, November 01, 2007

Mac Trojan In the Wild

http://www.boingboing.net/2007/10/31/mac-trojan-in-the-wi.html

Maybe the guy in the Mac commercial shouldn't be so smug next time.

Tuesday, October 23, 2007

My favorite Apple Leopard Features

Ahh it wouldn't be a good day if I didn't get to poke a bit of fun at Apple. Just going through the list of features gives me tons of reasons to upgrade

Boot Camp
Can't I download this for free as-is?

Desktop
"Enjoy an elegant, distinctive new look across the entire system. The semitransparent menu bar and reflective Dock frame your desktop picture. The active application window stands out with a deeper drop shadow and a distinctive toolbar color. One look at Leopard and you’ll know you’re in for something special."

Or I could just run Vista...

DVD Player
"Enjoy DVD Player’s dramatic new full-screen interface, which puts all your DVD’s features right at your fingertips. Mouse over the top or bottom regions to access onscreen semitransparent displays for a wealth of controls and settings."

Yes, truly groundbreaking...

Security
Firewall
"Gain more control over the built-in firewall. Specify the behavior of specific applications to either allow or block incoming connections."

Ya thats original

Library Randomization
"Defend against attackers with no effort at all. One of the most common security breaches occurs when a hacker’s code calls a known memory address to have a system function execute malicious code. Leopard frustrates this plan by relocating system libraries to one of several thousand possible randomly assigned addresses."

Apple: "We invented it first, then MS copied it!"

"Stronger Encryption for Disk Images
Give your data even more security. Disk Utility now allows you to create encrypted disk images using 256-bit AES encryption."

Can anyone say Windows 2000?

System
"Empty Trash Button
Empty the Trash from the Trash itself with the Empty Trash button."

My life will never be the same

Time Machine
Good thing Windows users haven't been enjoying this since Windows 2003.

Unix
"64-Bit Applications
Make use of all your existing devices. Leopard is the first mainstream operating system to completely and seamlessly support both 32-bit and 64-bit applications on the same platform."

Yes Apple, you are the first system to seamlessly support both 32-bit and 64-bit. Wait, then what I have I been running on my Windows machine for the last 2 years?

Xcode3
"Easily visualize your code's structure as you type with a unique highlighting effect, or use your mouse to select a code block to fold out of the way"

Once again Apple, you have raised the bar.....to Visual Studio 2003.


So all in all, there are 10 new real features?

Wednesday, October 17, 2007

New Blackberry firmware coming down the pipe?

My partner alerted me today to the fact that RIM has finally released 4.2 code for the 8700. I complained a while back that the 8800 code was buggy and in desperate need of an update - I can only hope that this is a sign of things to come!

Wednesday, October 10, 2007

Watch your Fill Factor

I was asked to troubleshoot an issue today with a 3rd party web application that was throwing some SQL Timeout exceptions while attempting to insert data into a database.

With the exception of long running queries, most timeout errors are caused by a few issues:

  • Runaway transaction logs
  • High fill factors
  • Missing clustered indexes

While I could probably write entire articles on each of these, I'm going to concentrate on the fill factors.

First, it's important to know that SQL Server itself does not have any timeouts; rather timeouts are implemented by the data provider (the .NET SQL providers) or the client (query analyzer, etc).

So what exactly is the fill factor? The fill factor is a parameter you set on indexes (both clustered and non-clustered); it controls the percentge of free space to leave on each page to leave room for future growth. Lower fill factors leads to less page splits. So why is this important? Well, page splits are expensive - they take a lot of CPU and disk resources to complete. So if you have a busy DB (lots of inserts into a table), and a high fill factor, then SQL server will have to constantly split pages to accomodate the growth, which might take longer then your timeout, resulting in a timeout error!

According to MSDN documentation (http://msdn2.microsoft.com/en-us/library/aa933139(SQL.80).aspx):

"Fill factor value is a percentage from 0 to 100 that specifies how much to fill the data pages after the index is created. A value of 100 means the pages will be full and will take the least amount of storage space. This setting should be used only when there will be no changes to the data, for example, on a read-only table. A lower value leaves more empty space on the data pages, which reduces the need to split data pages as indexes grow but requires more storage space. This setting is more appropriate when there will be changes to the data in the table."

In my particular case, I was able to resolve the timeout issue by changing the fill factor from 90% to 40%. Why 40% you might ask? The customer did not have overly large amounts of storage and decreasing the fill factor increases storage requirements - I could have set this to 0 but I didn't want to have an out-of-space condition to deal with, so 40% seemed reasonable to me.

Setting the fill factor via script is relatively easy and involves dropping the constraint and re-adding it with the new fill factor.

ALTER TABLE dbo.MyTableName
DROP CONSTRAINT PK_MyTableName
GO
ALTER TABLE dbo.MyTableName ADD CONSTRAINT
PK_MyTableName PRIMARY KEY CLUSTERED (
MyTableNameID
) WITH FILLFACTOR = 40 ON [PRIMARY]

Just something to watch out for when designing your DB's!

Friday, September 28, 2007

JavaScript Gotcha: Check for undefined before null

Do you see anything wrong with this line?

if (a !== null typeof(a) !== 'undefined') {
// Do something with a
}

... Well neither did I - but I've had users complaining of an application just giving them a "white screen" - typical of a JavaScript error to abort everything else. The second time I looked at it I could see what the problem was - I was checking for "a !== null" but a did not yet exist! The correct way to do this is

if(typeof(a) !== 'undefined' && a !== null) {
// Do something with a
}

Note to self: Always check undefined before null!

Tuesday, September 25, 2007

JavaScript Hashtable based on MS AJAX

I was looking to implement a JavaScript hashtable and after find a number of near identical implementations, I decicded to modify one that I found at http://alexrazon.blogspot.com/2006/11/javascript-hashtable-implementation.html to be based on the MS Ajax Patern.

Anyways, here it is:



Mbccs.Psp.Web.Manager.Hashtable = function() {
this._hash = new Array();
this._keys = new Array();
this._getEnum = new Array();
this._count = 0;
}

Mbccs.Psp.Web.Manager.Hashtable.prototype = {
getAt : function(index) {
return this._hash[this._getEnum[index]];
},

get : function (key) {
return this._hash[key];
},

remove : function (key) {
for (var i = this._keys.length - 1; i >= 0; i--) {
if (this._keys[i] == key) {
this._keys.splice(i, 1);
this._getEnum.splice(i, 1);
this._hash[key] = null;

this._count = this._keys.length;
}
}
},

put : function (key, value) {
if (value == null)
return null;
if (this._hash[key] == null) {
this._keys[this._keys.length] = key;
this._count = this._keys.length;
this._getEnum[this._count - 1] = key;
}

this._hash[key] = value;
}
}

Mbccs.Psp.Web.Manager.Hashtable.registerClass('Mbccs.Psp.Web.Manager.Hashtable');

if(typeof(Sys) !== 'undefined')
Sys.Application.notifyScriptLoaded();

Friday, September 21, 2007

Office 2003 SP3 Released

Microsoft seemingly quietly released Office 2003 SP3 - if you're not already running Office 2007, you can download the service pack at http://www.microsoft.com/downloads/details.aspx?familyid=e25b7049-3e13-433b-b9d2-5e3c1132f206&displaylang=en

Monday, September 10, 2007

Why does iTunes setup need to close Outlook?!

Everytime I update iTunes I remember why I left it so long - the install process is quite annoying! Can someone please explain to me why it's necessary to close Microsoft Outlook and Internet Explorer while installing iTunes?

It drives me even more crazy when I see Apple advertisements poking at certain annoyances in Windows yet Apple is usually the worst offender - Apple clearly does not understand the Windows environment, even though most of their software users are Windows users.

Now only if I could understand why it creates shortcuts everywhere meanwhile it only has 2 checkboxes to disable a few of them. grr!

Persisting the scroll position of child DIV's using MS AJAX


Introduction

While the ScriptManager and UpdatePanel found in Microsoft AJAX do a good job of persisting your pages scroll position during partial post back operations, you might be surprised to find out the same is not for scrollable child DIV's contained within an UpdatePanel.

The PersistentScrollPosition control presented in this article seeks to remedy this issue using a client-side behavior and ASP.NET server control implemented using Microsoft AJAX.


Background

While it is certainly not my intention to review the internals of the UpdatePanel and PageRequestManager or implementing any of the client-side components (Sys.Component, Sys.UI,Behavior, Sys.UI.Control), a quick understanding can go a long way into understanding and resolving this particular problem. There are two key items to keep in mind for this control:


  1. Client-side components are disposed of and recreated during the partial post back lifecycle so you can't use the controls instance to store any data you need to survive this.
  2. The HTML output of the UpdatePanel is completely replaced during a partial post back (assuming it was triggered) through the innerHTML property, which is why the scroll position problem exists in the first place.


Using the code

For those who just want the solution, using the code is straight forward. The control has one property you need to set named ControlToPersist. This is a string which takes the ID of the server-side container DIV (it must have runat="server").

<asp:UpdatePanel runat="server" ID="UpdatePanel" UpdateMode="always">
<ContentTemplate>
<asp:Button runat="server" ID="btnPostBack" Text="Post Back" OnClick="btnPostBack_Click" />
<br />
<div style="width:590px;height:400px;overflow-y:scroll;overflow-x:hidden;" runat="server" id="persistMe">
<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit...</p>

</div>
<mbc:PersistentScrollPosition runat="server" ID="psf1" ControlToPersist="persistMe" />
</ContentTemplate>
</asp:UpdatePanel>


Building the Control

The control consists of two parts, both of which for the most part are very "cookie cutter". On the server side, we inhert from Control and implement IScriptControl and INamingContainer and create a HiddenField during initialization to store our scroll position in between partial post backs.


public class PersistentScrollPosition : Control, IScriptControl, INamingContainer
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);

// Create hidden control for storage
storage = new HiddenField();
storage.ID = "storage";
Controls.Add(storage);
}}



When creating the script descriptors for the client-side initiation, we pass through the scrollable DIV's ClientID as the controls ElementID and we pass in a reference to the HiddenField's DOM element using the AddElementProprety method of the ScriptComponentDescriptor class.





public IEnumerable<scriptdescriptor /> GetScriptDescriptors()
{
ScriptComponentDescriptor scd =
new ScriptBehaviorDescriptor("Mbccs.WebControls.PersistentScrollPosition", Control.ClientID);
scd.AddElementProperty("storage", storage.ClientID);
yield return scd;
}


On the client-side, the control inherits from the Sys.UI.Behavior base class. Upon control intialization, it hooks into two events:
The scroll DOM event of the DIV, and the EndRequest event of the Sys.WebForms.PageRequestManager class. The EndRequest event is when the scroll state is restored, but I'll get to that shortly.


    initialize : function() {
Mbccs.WebControls.PersistentScrollPosition.callBaseMethod(this, 'initialize');

this._scrollDelegate = Function.createDelegate(this, this._onScroll);
this._endRequestDelegate = Function.createDelegate(this, this._onEndRequest);

var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(this._endRequestDelegate);

$addHandler(this.get_element(), 'scroll', this._scrollDelegate);

}



When the DIV is scrolled, the x,y scroll position is serialized and stored in the HiddenField server-side control we created earlier.


_onScroll : function(e) {            
this._storage.value =
Sys.Serialization.JavaScriptSerializer.serialize(this._getScrollPosition());
},

_getScrollPosition : function() {
var el = this.get_element();

if (el) {
return {
x: el.scrollLeft 0,
y: el.scrollTop 0
};
}
}


To prevent null's from floating around, the x,y coordinates are coerced into 0's if either the scrollLeft or scrollTop properties are null.

The EndRequest event is fired when "an asyncronous postback is finished and control has been returned to the browser," (http://asp.net/AJAX/Documentation/Live/ClientReference/Sys.WebForms/PageRequestManagerClass/default.aspx) so it's a perfect time to restore our scroll state.



_onEndRequest : function(sender, args) {        
var o = null;
if(this._storage.value !== '')
o = Sys.Serialization.JavaScriptSerializer.deserialize(this._storage.value);

if (o) {
var el = this.get_element();
el.scrollLeft = o.x;
el.scrollTop = o.y;
this._storage.value = '';
}
}

The dispose method isn't usually a place of any particular interest, but its worthy of noting that it you need to unhook the DIV's scroll event prior to calling dispose on the base class.

dispose : function() {            
$removeHandler(this.get_element(), 'scroll', this._scrollDelegate);

Mbccs.WebControls.PersistentScrollPosition.callBaseMethod(this, 'dispose');

var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.remove_endRequest(this._endRequestDelegate);

delete this._endRequestDelegate;
delete this._scrollDelegate;
}

Tuesday, September 04, 2007

Strongly typed URL's for ASP.NET

I came across an interesting article today on The Code Project titled Strongly typed URL's for ASP.NET by Brian Chavez which is a Visual Studio add-in that creates strongly typed classes for your site's file structure and navigation.

It's actually a neat concept - it creates a static class with strongly typed members that map to the actual files - if you ever change a filename, instead of worrying about updating it across the site, just use the generated class and you won't have any problems!

The only thing that I can see getting annoying is having to continually update the generated class - I suppose you could add this to your build process, but when first building a site, it might get tedious as you are constantly adding new files to the project structure.

In any event, it's worth a look!

Thursday, August 23, 2007

Yes, you can use C# controls in VB.NET code

I've been helping a student out using the Outlook-like Time Field Control I authored. She's been trying to port the code from C# to VB.NET. I've been trying my best to help her but unfortunatly it's been a long time (luckily) since I've had to deal with anything coded in VB.NET.

After a number of back and forths, I finally asked, "why exactly are you trying to port it over?" and her response was "surley i can't still use the control "as is" if its in C#?"

It seems that in all of her classes, no one failed to mention the CLS/Common Language Specification. She was even more surprised to hear that much of the CLR and .NET framework were authored in C#, even though she has been using it trouble-free in VB.NET.

Side note: If you are interested in why much of it is authored in C# I suggest you read Scott Guthrie's interview in the Architecture Journal.

This highlights one of the fundamental benefits of the .NET "world" - language neutrality. It doesn't matter if your coding in C#, VB.NET, Managed C++ or even Python.net for that matter, you can rest assured knowing that you can use components authored in any one of the supported .NET languages. Now that is productive!

Tuesday, August 21, 2007

Blackberry 8800 software update - where are you?

There is nothing more frustrating than a buggy handheld device - except for close to 5 months of bugginess! I've been a Blackberry user for years now and I've always been impressed with RIM's ability to crank out fixes and updates - that is, until the 8800. I picked mine up on March 31st, 2007 (no thanks to the 2 month hold-up), and within a few days had experienced a number of NullPointerExceptions, random other crashes, freezes, etc. "No worries, they'll fix it soon" I said - now, months later, I'm left wondering when they are going to fix all these issues!

I've heard rumors of a 4.3 handheld code for the 8800 - thats nice and all, but the 8800 has some serious flaws that deserve some fixes, sooner rather then later.

Am I the only one who has serious problems with this device?

Wednesday, August 15, 2007

C# ? operator - Nullable shorthand

The Nullable structure is a new generic structure to C# 2.0 which allows null values for value types (reference types obviously support this). This is useful in avoiding the magical "-1"'s and such.

The C# 2.0 compiler also provides a handy shorthand operator for this - ?.

To define a nullable integer you use one of the following statements:

Nullable<int> nullInt = new Nullable<int>();
Nullable<int>nullInt = new Nullable<int>(2); // Initialzie to 2

OR

int? nullInt;
int? nullInt = 2;


Console.WriteLine(nullInt.HasValue ? nullInt.Value.ToString() : "NULL!");

Very handy!

Monday, August 13, 2007

Assigning an programs output to a variable in a batch file

This one took me longer than it should have to figure out. I had to write a batch file to integrate with our monitoring appliance - I can't really remember the last time I had to do this, but the number 6.22 comes to mind.

Anyways, the goal was to set a variable's value to the output (note: note the exit code) to the variable. You can't do this with the SET command so I had to result to using the FOR statement.

From a command prompt, it looks like:

for /f "tokens=*" %a in ('Program.exe "argument1"') do set __VARIABLENAME__=%a

Only one gotcha - in a batch file, you need to double up your % identifiers.

REM This is the start of the batch file
for /f "tokens=*" %%a in ('Program.exe "argument1"') do set __VARIABLENAME__=%%a
echo Result is %__VARIABLENAME__%
REM This is the end of the batch file

I'm glad thats over, back to C# for me!

Wednesday, August 08, 2007

System.Net.WebException from XmlDocument.Load

I had a really bizzare problem today - I was loading a local XML document via XmlDocument.Load and it was throwing a System.Net.WebException - The remote server returned an error: (503) Server Unavailable.

I was totally stumped, and then I hapened to open the XML document in question (it's actually an XHTML document), and I noticed that the first line was a DOCTYPE with a link to an external DTD.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

Sure enough, following the
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd link gave me a 503 Server Unavailable error!

To resolve the problem I simply removed the DOCTYPE from the HTML document.

Tuesday, August 07, 2007

Choosing appropriate field lengths

For every project that I work on I seem to have the same argument with myself about field lengths (mainly when dealing with SQL) - just how long should they be? What is appropriate for first name, last name, and email address columns?

I used to start big, 100 characters for first/last name and 255 characters for email addressses. Recently I was revisiting my thinking of lengths so I decided to run some stats on the one of the larger DB's that I maintain. Here's what I found.

First Name: Max 27, Avg 6
Last Name: Max 27, Avg 6
Email: Max 76, Avg 22

The first thing that hit me was, geeze, a 76 character email address - that's a lot of typing! The second thing was that my column length allocations were on the really high (and unnecessary) end of the spectrum.

I always like to leave a bit of room because users always seem to do the unthinkable, so moving foward, my allocations look like:

First & Last name: 35
Email: 100

Since I mainly use variable length columns (varchar/nvarchar), storage is never really an issue, however when you start allocating 255 characters to each column it is easy to hit the table maximum (w/o BLOB's). Knowing that I can tone down my allocations gives me some re-assurance that I am less likely to reach the maximum when adding new columns down the road.

Thursday, August 02, 2007

Why don't things just work in Safari?!

When developing web applications, I primarily target Internet Explorer 6/7, and Firefox 1.5/2.0, but I do usually test things in Safari for layout purposes. While I rarley encouter any significant layout problems in Safari (other then its odd font rendering and super-thick anti-aliasing), the second I even think about a client-side component working I seemed to get slaped in the face, especially when it has something to do with callbacks.

I understand that Apple likes to do its own thing (ie: dock connector on the iPods - USB anyone?), but for god sakes, can't they support a similiar event model to another browser? Granted, Firefox and IE implement different event models too, but at least they are a bit more straight forward to abstract and work with.

And that is just with Safari 2.0...Don't even get me started about 3.0 (I'd have more to say if it didn't crash everytime I tried to run it on one of my workstations).

Whats most frustrating is that they've done a good job at supporting layout standards (they even pass the ACID2 test), but from a programming point of view, its a nightmare. And built in debugging tools? Useless - I get random null references on lines that don't exist and no errors when there actually is a problem.

Frustrating!

Monday, July 30, 2007

Standards-based layout saved my day!

I can always count on my clients for some last minute urgent changes - I’ve come to expect it - in fact, I even plan for it (similarly to how I tell all my late friends that things start an hour earlier than they actually do.) I had a change come up on Thursday afternoon that needed to be completed for Monday morning if possible. It involved a color scheme update, new menu items and a few additional design elements. My first reaction was “great, this is going to take a few days…” but after opening up the project to take a look at what actually needed to be changed I was pleasantly surprised – it didn’t look like I needed to make any markup changes (with the exception of changing a few words – Fundraising to Fundraise, that kind of stuff).


Four hours later (most of it spent in Photoshop slicing images and testing in various browsers), the update was complete. No HTML changes, just a bunch of new images and about 20 lines of CSS to change, amazing!


One thing that really saved me was having an extra wrappre-DIV around the main content.




This allowed me to easily add the circles that appear in the bottom right corner.



Without the wrapper-DIV I likely would have to either added it to the markup or gotten really creative with the CSS on the mainbody DIV. Not to say that it wouldn’t be possible to do, just that having it there (it wasn’t really necessary for the original design) made my life that much easier.


The final results:

Before:



After:



To top everything off, the homepage comes down in about 3.7kb of HTML markup which means it loads wicked-fast even on my Blackberry. And of course it gracefully renders to down-level clients without CSS support.

Unable to stop or use COM+ component

I just had a really bizzare issue on my home workstation. I was having trouble accessing a COM+ component that has always worked - the error was a standard issue Access Denied. All the permissions looked fine. I thought maybe it was having difficulty accessing a file or registry key so I pulled up Sysinternals ProcessExplorer and ProcessMonitor to take a look under the hood - and then I noticed something odd: The account it was running under was showing as . The only change I had made recently was to hide the account from the Windows login screen (HKLM\Software\Microsoft\Windows NT\Current version\Winlogon\SpecialAccounts\UserList) - sure enough, after I removed this entry it worked as expected.

Thursday, July 26, 2007

Visual Studio 2008 Beta 2 is released

Microsoft has just released Microsoft Visual Studio 2008 Beta 2 (in all flavors - standard, pro, team suite, and TFS). It can be downloaded here: http://msdn2.microsoft.com/en-us/vstudio/aa700831.aspx

MBC is a Microsoft Certified Partner!

MBC is now a Certified Member of the Microsoft Partner Program as of Tuesday July 3, 2007.

We have achieved our Networking Infrastructure Solutions Competency. By achieving this competency, MBC has proven that we have the ability to craft infrastructure solutions for small to midsize businesses that include Windows Server Solutions based on the Microsoft Windows Server 2003 or Windows 2000 Server operating system, or Microsoft Small Business Server 2000 and Windows Small Business Server 2003. These implementations may include crafting solutions that connect Windows-based servers, PC locations, and the Internet; installing a server farm; or building a Windows Small Business Server stand-alone solution that includes file/print capabilities.

Wednesday, July 25, 2007

A simple way to handle data collection in email submission forms

Frequently I get asked to create a simple web-form that collects a few peices of information and either stores it or sends it to someone as an email - pretty straight forward... Where it gets annoying is when someone asks for a change and you end up messing with a bulk of string concatenation code.

A really simple solution to this problem is to place all of your controls in a panel, and then loop through the panel's controls collection and create a NameValueCollection with all of the questions/answers - which can then easily be stored or emailed off.

The code looks something like:


NameValueCollection answers = new NameValueCollection();

answers.Add("Date", DateTime.Now.ToString());

foreach(Control c in panelName.Controls)
{
switch(c.GetType().Name)
{
case "TextBox":
answers.Add(c.ID, ((TextBox)c).Text.Trim());
break;
case "DropDownList":
answers.Add(c.ID, ((DropDownList)c).SelectedValue);
break;
case "RadioButton":
answers.Add(c.ID, ((RadioButton)c).Checked.ToString());
break;
case "RadioButtonList":
answers.Add(c.ID, ((RadioButtonList)c).SelectedValue);
break;
}
}

FormMailer.SendResponses(answers);

Tuesday, July 24, 2007

New version of Nikhil Kothari's Web Development Helper

If you haven't already used Nikhil Kothari's Web Development Helper IE plug-in for debugging and tracing web applications, it’s an indispensible app to have in your toolbox. It has been further updated to support class browsing of classes registered within MS AJAX.

You can read the related blog entry at http://www.nikhilk.net/Entry.aspx?id=168 or download it directly from http://projects.nikhilk.net/Projects/WebDevHelper.aspx

Friday, July 20, 2007

JavaScript Support in Visual Studio 2008 looks like its shaping up

Two of the features I'm looking forward to the most in Visual Studio 2008/Orcas is JavaScript Intelli-sense and debugging support.

Scott Guthrie has a few posts worth checking out by the most recent shows off some of the debugging features - http://weblogs.asp.net/scottgu/archive/2007/07/19/vs-2008-javascript-debugging.aspx

Thursday, July 19, 2007

Using Web Standards to Simplify Web Control Development

Introduction

I've been an advocate of web standards for some time now and I'm frequently surprised to find new ways to simplify seemingly unrelated tasks. This article discusses how web standards can be used in ASP.NET control development to simplify some development tasks, build lighter weight and accessible controls and increase layout flexibility.


Background

This article assumes that you have a basic understanding and knowledge of Web Standards. If you need a primer there are a ton of references out there – one of my favorite being A List Apart.


Typical Scenario

You've probably built a glorified sign in page before using nested tables and lots of spacer images to control layout (see Traditonal.aspx in source) and a handful of properties to control how it is rendered. It may have even looked something like this:



Your HTML code probably resembled this:


<table>
<tr>
<td>
<table>
<tr>
<td></td>
</tr>
<tr>
<td></td>
</tr>
</table>
</td>
<td></td>
<td>
<table>
<tr>
<td></td>
</tr>
<tr>
<td></td>
</tr>
</table>
</td>
</tr>
</table>


Like all good developers, you built a web control to handle its functionality so you could reuse it across sites. I've added a property named LayoutDirection to control swapping the two boxes left and right positions.


When it comes to custom control rendering of such controls, you probably often find yourself with if-else blocks scattered throughout your rendering code.


private void BuildControlTree()
{
Controls.Add(new LiteralControl(@"
<table style=""width: 100%"" cellspacing=""0"" cellpadding=""0"">
<tr> <td style=""width: 45%"">"));

if(LayoutDirection == Direction.Standard)
BuildNewCustomers();
else
BuildExistingCustomers();

Controls.Add(new LiteralControl(@"</td> <td style=""width: 10%""> </td>
<td style=""width: 45%;text-align:right;"">"));

if(LayoutDirection == Direction.Standard)
BuildExistingCustomers();
else
BuildNewCustomers();

Controls.Add(new LiteralControl(@"</td></tr></table>"));
}


This has the following drawbacks:

  • Your code is cluttered with excess HTML


  • Making changes is prone to errors because you often have to cut up the fragments further and matching tags properly in a code view can be difficult


  • Adding properties to control the layout usually results in scattered if-else blocks.


  • Styling options are not very flexible without a property for each option


  • Difficult to navigate and use on mobile devices such as a Blackberry



Using Web Standards

I always like to start with a barebones structure and then apply styling afterwards. The goal is to keep the presentation near identical. All we need here is a DIV for each box and something to designate a title (I choose the H3 tag in this case).


Our final HTML markup should look something like (See Standards.cs and WebStandards_Bare.aspx):


<div>
<div id="signupdiv">
<h3>Sign Up</h3>
<p>New customers <a href="#">click here</a></p>
</div>
<div id="signindiv">
<h3>Sign In</h3>
<p>Existing Customers Sign In Below:</p>
Email: <input type="text" /><br />
Pass: <input type="text" /><br />
<input type="submit" value="Sign In" />
</div>
</div>


The rendered output looks like:



Now all we need to do is apply some styling to get it looking right. For simplicity I assigned each DIV an ID in the web control and referenced it in CSS by ID. In the real world you would probably want to expose properties to control the CSS class assigned to the DIV. Our final CSS looks like:



#signupdiv, #signindiv {
width: 45%;
border: 1px solid #000;
padding: 1px 1px 0 1px;
text-align:center;
height: 175px;
}
#signupdiv
{
float:left;
}

#signindiv
{
float:right;
}

#signupdiv h3, #signindiv h3
{
color: #fff;
background: #444;
text-align:center;
width: 100%;
height: 25px;
font-weight:normal;
}


Remember how in the traditional model I added a property named LayoutDirection to the web control so I could swap the left and right boxes? That's no longer needed thanks to the floating techniques available. Not only did we remove an entire property block from our code, we replaced it with two lines of external CSS code!



Side-By-Side Comparison



We've accomplished identical layouts using both techniques, so how do they stack up next to each other? For simple tasks like this I often like to look at two factors: number of lines of code, size of rendered output. I know that line counting isn't a practical measurement for most projects, but in this case I think it's a good gauge of simplicity.





















































 



Traditional




Standards Based



% Change



Web Control Lines of Code



128




55




-57%




Rendered HTML Page Size





1,899 bytes





1,224 bytes




-35%




Easily viewable on Blackberry handheld




No




Yes




N/A




Easily viewable without style sheet?




No




Yes




N/A





Points of Interest



If you have been paying attention you might point out that I've excluded the size of the external CSS document (which, by the way, is 361 bytes). The reason for this is that because it will be cached by the browser, it only needs to be downloaded once.

Unable to create bookmarks in IE7 - "Unspecified Error"

I just had a somewhat interesting security problem in Vista that I thought I’d share.

The problem was in Internet Explorer when creating a bookmark, I’d receive a message “Unable to create [URL]. Unspecified error”. The problem only occurred in protected mode websites which led me to believe it might have been a permissions issue. Indeed, trying to propagate my local account with full access generated an Access is Denied error, so I replaced ownership on the folder successfully, however the problem was still occurring. A bit of research later and here is what I discovered in a nutshell


- Windows Vista introduces a new concept called “Integrity Level”. Basically, along with every ACL, there is also a “class” – this defines what types of applications can modify a particular file.

- By default, all files allow “Medium” or higher applications to modified them, however Internet Explorer running Protected Mode runs at a “Low” integrity level (basically, IE can only directly write to files with a Low integrity level associated with them, otherwise, the write has to go through the protected mode broker process which runs as a medium level application)

- The icacls command line utility (introduced in W2K2 SP2 and Vista) includes a new switch that allows you to set the integrity level

To resolve the issue, navigate to c:\users\USERNAME and run the following command against the favorites folder:

icacls Favorites /setintegritylevel (OI)(CI)low

The (OI) and (CI) stand for “object inherit” and “container inherit” respectively (propagate permissions basically), and the low is pretty obviously assigning a low integrity level requirement to the file.

[Updated: June 19, 2008 - Step-by-step instructions due to popular demaind]

Step-by-step Instructions

 

  1. Choose Start -> Run
  2. Type "cmd" (without the quotes) and press OK
  3. Navigate to your user folder.  By default, this is c:\users\Username.  In my case:

    cd /d c:\users\steven
  4. Run icacls:

    icacls Favorites /setintegritylevel (OI)(CI)low

 

The sequence should look like this:

icacls