22 October 2006

A better way to fix the TreeView's invalid <script> attribute

I was poking about in Reflector today and think I found a better way to fix the invalid <script> attribute that the TreeView control insists on putting out when the EnableClientScript attribute is set to "true".

The root of the problem seems to be a static private field in the TreeView control called "populateNodeScript" which contains the hard-coded (!) <script> tag - my solution uses reflection to fix this string so that when the TreeView uses this value it uses the fixed value rather than th default.

This is the code that needs to be placed in the OnInit handler of your page (I use OnInit but anywhere before OnPreRender should do the trick):

private static void FixTreeViewScriptNode()
{
FieldInfo field = typeof(TreeView).GetField("populateNodeScript",
BindingFlags.NonPublic | BindingFlags.Static);

string populateNodeScript = Convert.ToString(field.GetValue(null));

field.SetValue(null, populateNodeScript.Replace("<script>", "<script type="\">"));
}


Note: I'm not sure of the performance impact of this script as I havent had much of a chance to performance test it yet - I expect the reflection penalty will have less of a hit (memory-wise anyway) than the render-to-string HttpHandler method I have detailed before. There is always scope for improvement - as we're setting a static field then we should only need to set this once, though I'm unsure when or where (global.asax?)

19 September 2006

Fixing TreeView control rendering

While I'm on the subject, I thought I would go over another more annoying bug with the .NET framework which affects the TreeView control and (X)HTML compatibility.

The jist of the problem is that when using the TreeView control with client-side script it has a tendancy to render a <script> tag without the required "type" attribute, very annoying seeing as Microsoft likes to sing the praises of the new standards-compliant control rendering in .NET 2.0.

As a fix you can use the same Render method override trick as before, adding in a simple Replace for these non-compliant script tags:

protected override void Render(HtmlTextWriter writer)
{
string renderedHtml = String.Empty;

using (System.IO.StringWriter sw = new StringWriter())
{
HtmlTextWriter newWriter = new HtmlTextWriter(sw);

// Render "MyBase.Render()" to a String instead of the writer

base.Render(newWriter);
newWriter.Flush();
renderedHtml = sw.ToString();

newWriter.Close();

}

// Fix broken (incompatible) <script></script> blocks, such as the one emitted by the TreeView control
renderedHtml = renderedHtml.Replace("<script>", "<script type="\">");

// Write the modified HTML String to the Response's writer
writer.Write(renderedHtml);
}

This also has the added bonus of fixing any other broken script blocks in the currently rendered page
, which is nice..

Moving ViewState to the Bottom of the page

I was researching some weird ViewState bugs today and stumbled across this post on moving the ViewState to the bottom of the page. The main point of this is SEO; I seem to recall that Google (and possibly other search engines) only read the first xkb of a page, so when a page has a fair few kb of ViewState on it this can screw up your SEO and mean information you want indexing doesnt.. (get..)

Enter Scott's method. It's pretty straightforward really, you're just physically moving the field to the just before the end of the form tag. The one problem I have with his method is that with .NET 2.0 in XHTML compatibility mode the ViewState field is wrapped in a <div> tag as you're not allowed <input> elements in the root of a form tag. Scott's method breaks this convenient addition by moving the __VIEWSTATE input field out of the div, what we ideally want is the dv moving too, hence I came up with a new version of the Regular Expression he uses:

(<div>[^<]*<input.*name="__viewstate"[^>]*>[^<]*</div>)

All pretty straightforward, you may notice that I chose to strip out the type="hidden" part of the original Regex so as to make things a bit more more generic. I havent delved into the (faster) non-Regex method Scott outlines as I personally think the Regex method is more readable - feel free to give it a try if you like.

Ubuntu Woes

Well, I recently decided to splash out on a new box. Hardware specs aside I thought as an experiment I would go the linux route with this one - you know, install Ubuntu, MythTV and maybe try some Mono development on it.

Now, I hear that the linux desktop is approaching maturity, but I'm not sure I see it. After running, or attempting to run, Ubuntu for several weeks I thought I would post my thoughts (both positive and negative)..
  1. PRO: Installation was relatively easy, I like the idea of the installation CD booting you into a live desktop before you start the installation process very handy especially for recovery.
  2. CON: Installation was buggy. At one point you choose (it appears) which drives you would like available in the final install and where to mount them. It then proceeds to format the aforementioned drives that you have been filling with data for the last 4 years into NTFS and before you notice, oh well..
  3. PRO: Once started, installation was very straightforward and quick, equalling Windows in it's simplicity.
  4. CON: First restart after installing I was greeted with a flashing cursor on a black screen. Turns out Grub didn't like my 4-port SATA controller. Luckily my new motherboard has enough free SATA ports that I could cut the controller out of the equation (for now).
  5. CON: The default ATI drivers are pretty shoddy, and after upgrading to what I though would be better performance drivers it totally broke all video playback through banshee, xine, mythtv etc. I'd play a movie and get unceremoniously dumped back to the login screen (the lack of blue screen would be, I suppose, a PRO though)
  6. PRO: NTFS support is coming on in leaps and bounds, the NTFS-3g project is testament to this and runs excellantly.
  7. CON: As part of the hardware upgrade I had decided to copy the data from my old RAID array (A Highpoint RocketRAID 133) to one of my shiny new SATA drives. Unfortunately the DIY linux drivers on the highpoint site don't seem to like 64-bit OSes - I could mount the drive and see the files on it, but on trying to copy the files the process would hang indefinitely with little to no sign of progress. After giving it some space (left it for 2 days with no noticable change, the rest of the system was stable) I gave in and decided to find another machine to grab my data.
  8. PRO: I'm liking the Synaptic package manager and general apt-get commands, very useful.
  9. CON: You're pretty much tied to the packages the community have added to Synaptic. If you want something that people haven't thought to add, or you want/need the latest version of something existing (I'm a bit of a cutting-edge whore as you will find out), then you pretty much need to compile from source (along with the other dependancies of the program). Whatever was wrong with installer programs, a-la Windows? Why should I need to "./configure", "make", "make install" every time I want to install something? If it's that easy then why don't they lump it all into one command?
  10. CON: Something needs to be done about DVD playback. Once you get through all the legal issues and finally get libcss or whatever installed then it's still buggy - jumping video and pixelated picture even on my shiny new Core 2 Duo box.
Well I'm sure there's more, for the time being I've installed Vista RC1 (not without it's issues but that's another post entirely). I still need to get back into linux to sort a couple of things (foolishly re-formatted a drive in xfs or whatever), which means re-enabling grub after Windows overwrote the MBR, Ho Hum..

First post! (oh god..)

Well, I have a blog.. I'm going to try and keep this blog for the techie among us, rather than taking the random approach (not that I have anything against that Chris!).

I'm going to blog about XHTML/CSS, .NET, Linux, Windows and general technology, and hopefully not get too sidetracked along the way.

Enjoy the blog!