<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.

Comments

ASB said:

Love your custom theme...

Which editor are you using to be able to display the code samples?

NinjaFish said:

Thanks!

For the code samples, I use a random code formatter that I found at http://www.manoli.net/csharpformat/. You can use the form on his web site, but for personal use, I downloaded the source and built it into an executable. I just paste the resulting HTML into BlogJet and that's it.

I've actually built this same code into a CS module. Unfortunately, it's a little bit quirky when using the CS text editor because of the way it handles quotation marks, but I can get it to work properly with BlogJet.

BlogFish said:

[Update] Due to something else I&#39;m working on, I&#39;ve shortened the name of the control to just

Community Server Bits said:

Justin Pierce with thoughts about the Community Server SDK and its precognition of ASP.NET 2.0 features,