Tuesday, December 18, 2007

SharePoint Quirks Mode? Booooooo!

To understand my plight, you need to understand DOCTYPE. Basically, long ago IE and others agreed to certain standards and behavior. That was a huge step for standards, and played a big role in making today's modern AJAX components possible. When they did it, they needed to preserve backwards compatibility. So, HTML pages need to include the DOCTYPE at the top, which basically indicates the version of HTML the browser behaves for. It's simple, and most modern pages include it. In fact, it's included in all new ASPX pages in Visual Studio by default:

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


If you don't have that line, browsers will go into Quirks Mode, where all the old idiosynchrasies are present. In Grid FX, we have popups and perform certain layout operations that Quirks Mode chokes on. No big deal, because we just told people to add that above line at the top of the page, which they should be doing anyway. So you'd think a very major web-based portal system like SharePoint would surely include it, right? Nope!

SharePoint, even the latest version, doesn't include that line. And if you do in fact include it, all of SharePoint's menus go wacky, because they have designed the system around all that screwed up old crap. Seriously? This is pathetic. Really pathetic.

Even controls written under ASP.NET AJAX won't work, because some don't behave correctly in Quirks Mode. Why would you worry about that when it's been many years since they changed the browsers? Can't they just change SharePoint? Yeah, sure. Best of luck.

What really sucks is that we need to have Grid FX work in SharePoint. People have already been asking about it. So now I gotta go through everything and make it work in Quirks Mode. I'm going to fly to Redmond, poop in a bag, light it, and set it on the step of the SharePoint building.

Thursday, December 13, 2007

Found my first silly coding mistake in the .NET framework

One thing I need to do to get Grid FX working in Visual Studio 2008 is to render all style attributes inline, as opposed to the embedded css classes that it was currently doing. Anyway, I spent the better part of my day changing the system (for the better in my opinion, which makes me happy). No real problems until I got a strange IndexOutOfRangeException when I called HtmlTextWriter.AddStyleAttribute more than 20 times. The HtmlTextWriter does just what its name implies - it writes the HTML for the control. The style attribute and value were perfectly valid. I couldn't find anything wrong on my side.

A while ago I used a Reflector add-in to decompile most of the .NET framework DLLs. This really comes in handy when I need to know what's really going on inside the framework. So I pulled up the method in question and found the following code (omitting the irrelevant parts):

protected virtual void AddStyleAttribute(string name, string value...

{

if (this._styleList == null)

{

this._styleList = new RenderStyle[20];

}

else if (this._styleCount > this._styleList.Length)

{

RenderStyle[] styleArray1 = new RenderStyle[this._styleList.Length * 2];

Array.Copy(this._styleList, styleArray1, this._styleList.Length);

this._styleList = styleArray1;

}

this._styleList[this._styleCount] = style1;

this._styleCount++;

}



It fails on call #21 (and 41 and 61, etc) because the person who wrote it made a very simple mistake. The line "this._styleCount > this._styleList.Length" should have used >=. Wow, such a simple error. Oddly, the AddAttribute method had pretty much the exact same code without that mistake.

It's kinda scary because you would think that if you go that route of writing code to expand an array size that you would test the limits, especially if you hardcode 20 as the initial limit. Bad coding, maybe, but it's the weak testing that I blame.

I would like to point out that you probably won't ever hit this bug because you really shouldn't use a ton of inline attributes. We do it only at design time, because the css attributes from Grid's Palette and Motif can be many, mainly because they are split into individual styles (padding-top/left/right, border-top-width, etc) rather than composite attributes like padding, border, etc. So I guess we could be the first ones to ever render more than 20 style attributes. Good thing I use external style sheets at runtime and don't have to deal with the inline style mess.

Well shit, what do I do now? I suppose I could write them and point it out. But that won't do much good because the libraries can't change. So I tried some ideas and had some luck...

I used reflection to increment the "_styleCount" field when that exception occurs. This will cause the next call to AddStyleAttribute to actually run the code to double the array size, because "this._styleCount > this._styleList.Length" will evaluate to true. This is a little dangerous because the array would have an empty element, and I could get another exception down the line. Thankfully that didn't happen, because the object in the array is a struct called RenderStyle, and is never null...and the code to write out the attributes checks against a null key or value.

So I wrote some helper methods and stuck them in a utils class. Here they are. Calling these AddStyleAttribute methods instead of the writer's AddStyle attribute would be smart. Using these calls will bypass that error. I would have preferred to use C# 3.0 extension methods instead, but I can't because we compile Grid FX off framework 2.0. Oh well, this is good enough.

///

/// Calls the HtmlTextWriter's AddStyleAttribute method, bypassing an exception that will occur after the 20th call. Th

///

public static void AddStyleAttribute(HtmlTextWriter writer, HtmlTextWriterStyle key, string value)

{

try

{

writer.AddStyleAttribute(key, value);

}

catch (IndexOutOfRangeException e)

{

IncrementHtmlTextWriterStyleCountField(writer);

writer.AddStyleAttribute(key, value);

}

}

///

/// Calls the HtmlTextWriter's AddStyleAttribute method, bypassing an exception that will occur after the 20th call. Th

///

public static void AddStyleAttribute(HtmlTextWriter writer, string name, string value)

{

try

{

writer.AddStyleAttribute(name, value);

}

catch (IndexOutOfRangeException e)

{

IncrementHtmlTextWriterStyleCountField(writer);

writer.AddStyleAttribute(name, value);

}

}

///

/// Increments the HtmlTextWriter's _styleCount field. Used to bypass a bug in the framework where IndexOutOfRangeException is thrown on the 21st, 41st, 81st, etc call to AddStyleAttribute.

///

private static void IncrementHtmlTextWriterStyleCountField(HtmlTextWriter writer)

{

//as an optimization, get the FieldInfo lazily and cache it for subsequent hits, since the lookup is the major piece of work.

//a double check locking technique is used to be thread safe but only use locking if the FieldInfo hasn't been cached.

if (m_htmlTextWriter_styleCountInfo == null)

{

lock (m_htmlTextWriter_styleCountLockObj)

{

//check again for null in case two threads entered the above if block and the first one exited the critical section

if (m_htmlTextWriter_styleCountInfo == null)

{

m_htmlTextWriter_styleCountInfo = typeof(HtmlTextWriter).GetField("_styleCount", BindingFlags.Instance | BindingFlags.NonPublic);

}

}

}

int currValue = (int)m_htmlTextWriter_styleCountInfo.GetValue(writer);

m_htmlTextWriter_styleCountInfo.SetValue(writer, currValue + 1);

}

static FieldInfo m_htmlTextWriter_styleCountInfo;

static object m_htmlTextWriter_styleCountLockObj = new object();



See ya.

Friday, October 12, 2007

Yeah I still use TABLEs. Wanna fight?

The use of the TABLE element in HTML has created more controversy than the Da Vinci Code and Rev. Al Sharpton combined. On one side are the guys who use tables for laying out everything in their sites. Bad form. On the other side are the fanatics who bash everyone who uses tables anywhere. Lunatics.

If you use Grid FX, you'll notice that I use tables in some situations where it may not seem necessary. For example, the elements for the pager (navigation buttons, "Page 1 of x", a text box) are in a table.



I didn't want to do this but I had no other choice.

I use tables to satisfy these requirements:
1. No explicit width/height necessary
2. Shrink wraps to width of contents
3. Vertically aligns content in the middle. [More Info]

Believe it or not, you can't achieve this with DIVs or SPANs. Divs cannot shrink wrap and do not verically align in the middle. There are tricks around that but they require explicit sizes. Because the Grid is a component, every little piece must be customizable. I can make no assumptions on size or I will be screwed. I also played around with the float attribute but was disappointed when it had some adverse effects on layout.

In FireFox, there is a way to do this with DIVs and a special display attribute. So instead of:
<table><tr><td style="vertical-align:middle">.... I can do <div style="display:table; vertical-align:middle">

But then I have more code to write. I am currently working on some FireFox enhancements and issues and will probably build this optimization in. However, it will give no real performance boost and will only serve to make the DOM a little cleaner. What would you do?

Thursday, October 11, 2007

Code Idol

I was looking up .NET user groups that I could visit to talk about Grid FX. First up was the Florida .NET user group. When I pulled up the web site, there was a mention of an upcoming code contest that followed the American Idol format, and was cleverly dubbed Code Idol. I saw this and had to enter. It looked like a lot of fun. At first, I was gonna submit a small class that I use internally in our controls. I call it Operation Controller, and I'm gonna post it up at some point because I think it's a great example of abstracting a common problem. Anyway, as the contest approached, I decided to change my entry to something more relevant to the audience at the contest.

I entered something I call "Cache Register", which is basically a distributed .NET caching service that is meant to be used primarily by ASP.NET applications for removing the infamous ViewState hidden field and delivering dynamic images. There was one feature in particular that offloads any image processing from the UI thread to the cache service. This feature makes an obvious difference in performance. What's even cooler is that we provide this kind of technology with our products...we call it PSS. Maybe one day we'll turn it into full fledged product rather than an internal piece of our products.

Despite taking way too long and starting off way too slowly, I won! I think that showing some nifty multithreading code might have tipped the scales. Perhaps not. Either way, I was really happy. Other guys had great entries and I learned some really cool new stuff. I wish there was a similar contest at a bigger level. Then I can be like the little girl who wins the local town beauty pageant and wants to leave and become Miss America.

I had a good time and will be attending future meetings. Hopefully they'll let me give a regular presentation about Grid FX. I think that instead of focusing on the product, I'll focus on one specific technology area, like viewstate, css, ajax, control designers, etc. That will be a lot more fun and beneficial for the group...and for me.

Below is a copy of the results. Also, the group leader, Dave, posted the results on his blog. Thanks Dave!



CODE IDOL RESULTS!

All the code Idols did a great job. In the end, mostly by popular vote, Steve Potter won the "Top Geek" title.
I'm sure we will see more of Steve as he is very interested in presenting at future meetings!
Thanks to the code idol contestants:

Steve Potter - Cache Register
Jonas Strawski - SQL Server as Document Repository
Lou Yovin - Volume Shadow Copy
Tim Corbett - System Tray App
Louis Datz - dashCommerce

Martin Anderson - XML Schemas and powershell
Max Trinidad - Powershell script to create CSV file

Thanks to Shervin Shakibi for the concept and being a judge, MC and judge Dave Noderer and Jeff Barnes of Microsoft who was the "Mystery Judge".

Wednesday, October 10, 2007

Grid FX

I am the lead developer for an ASP.NET grid control called Grid FX. There are plenty of aftermarket grids out there and many of them are really good. And 2007 is a little late in the game to introduce a new player. So then why did Software FX throw its hat in the ring? I think it's because nobody is really dedicated to making the best grid on the market. Most component companies create a grid to round out their bundle, and then do little afterward.

I know this because I actually wrote a grid and shopped it around to component companies. While most were interested in adding a grid to the product line, none cared about creating something new. They all basically wanted to offer a GridView with a nicer UI. But I saw so many opportunities for improvement from UI to design time to even real specific areas like ViewState (oh man do I have a good post about that).

And so did Software FX, which is why I partnered with them. After arriving, we spent many months just designing this thing...more time that some others take for their entire development process. This company has amazing people. Serious serious talent. I'm confident Grid FX will soon be known as the greatest grid ever made.

Anyway, I'll talk more about the details as I go along. I hope this didn't come across as arrogant or belittling, because there are many great offerings out there in addition to what we make here in Florida. I just wanted to explain the level of devotion I have to improving web applications and bringing smiles to the developers who create them.

To new beginnings

For a long time I've wanted to become a contributor to the software developer community. And for even longer, I've procrastinated and avoided committment. Luckily, there are about a million corny catch phrases that can be used to describe fresh starts. And while mentioning one might be considered appropriate....just too cynical for that.

Perhaps I was waiting for some big event. I suppose the release of Grid FX will do. After all, what better way to celebrate a project that took over two years to complete than by starting a blog, right? So here we go....