3
Aug
2006
<CS:Head> Renders a Head Tag
One of my favorite things about Community Server is the SDK, which is really nothing more than the CS source code. I guess they call it an “SDK” because it really does help with developing new CS stuff. If you’ve been developing with ASP.NET for a while and you take a look at the CS 2.0 SDK, you can almost immediately tell that they knew what was coming with ASP.NET 2.0 and implemented ASP.NET 1.1 versions of much of that functionality. It’s almost forward-thinking, but I suspect they were cheating. 
So I was bored one day and was trying to shoehorn Atlas into Community Server, much like Reese’s shoehorns peanut butter in their chocolate, when I ran into a rather silly issue. In order to enable partial rendering on the Atlas ScriptManager (and let’s face it: what fun is Atlas without partial rendering?), you need a head tag with runat="server" on it. Easy enough: I’ll just add runat="server" to…wait a sec! What’s this <CS:Head> thing?!
It turns out that <CS:Head> is like an ASP.NET 1.1 version of <head runat="server">. It allows you to programmatically access the contents of the <head> tag at any point during page rendering, just like you can do in ASP.NET 2.0. The problem is that it renders the <head> markup, so if I just wrap it in <head runat="server">…well, I’d have two <head> tags, and we can’t have that, can we?
The solution I came up with was to replace <CS:Head> itself. I still need its functionality so that CS can provide me with the correct scripts and stylesheets. I just don’t need its errant <head> tag.
using System.IO;
using System.Text;
using System.Web.UI;
using CSControls = CommunityServer.Controls;
namespace NinjaFish.CommunityServer.Controls
{
/// <summary>
/// Renders the contents of the Community Server Head tag without rendering the
/// HTML head tags themselves.
/// </summary>
public class HeadContent : CSControls.Head
{
protected override void Render( HtmlTextWriter writer )
{
// Intercept the output of the base class and store it in a StringBuilder.
StringBuilder baseOutput = new StringBuilder();
HtmlTextWriter intercept = new HtmlTextWriter( new StringWriter( baseOutput ) );
base.Render( intercept );
// Remove the <head> tag from the output.
baseOutput.Replace( "<head>", string.Empty );
baseOutput.Replace( "</head>", string.Empty );
// Dump the new output out of the control.
writer.WriteLine( baseOutput.ToString() );
}
}
}
To use this, I do something like the following:
<head runat="server">
<nf:HeadContent runat="server">
<CS:AllTheCSHeadGuts runat="server" />
</nf:HeadContent>
</head>
The output is exactly the same as it was before I started messing around, but now the ScriptManager no longer complains about its missing head.