Add to My Yahoo! | Google Reader or Homepage | Add to Windows Live | Add to Windows Live Alerts

Wictor Wilén

Microsoft Certified Master (MCM) - SharePoint 2010 | Microsoft Most Valuable Professional (MVP) - SharePoint Server MVP | Author

Get rid of the annoying SPAN tags in SharePoint 2010 pages

Posted at 2011-04-18 09:35 by Wictor Wilén in SharePoint 2010 with 9 comments.

For quite some time I've been pretty annoyed (and that's an understatement) of the strange span-tags generated by the output of pages in SharePoint 2010. Not only are they annoying they also make the markup invalid, since the span tags are omitted after the closing html tag (duh!).

Spans, spans, spans

So in order to get to the bottom of this I decided to face my fears and entered debugging mode. It only took me a few minutes to find out what was going wrong, and I didn't even have to step (almost) through any SharePoint code to find it out. Here's what I found and how I found it...

First I enabled the Developer Dashboard and turned on the ASP.NET page trace. I immediately noticed the following controls being added to the control tree at a suspicious location. The SPPageStateControl, a top-level control in the control tree, had 17 child controls - the exact same number as empty span tags being omitted. Probably not a coincidence.

The mysterious controls...

I checked the master page (v4.master) and could not find the SPPageStateControl. It must be inserted dynamically then, so I fired up Reflector and did an analysis of that control and found out that it's instantiated by the WikiEditPage during the OnLoad event. And the control is inserted directly as a child to the page object. Hence the rendering of the span-tags after the closing html tag. The SPPageStateControl inherits from SPControl (which inherits from Control) and produces no output - so this one was not the bad guy.

I turned to the child controls (SaveCommandHandler etc) which all are inheriting from SPRibbonCommandHandler. And the SPRibbonCommandHandler inherits from the WebControl - if you know your ASP.NET basics then you know that a WebControl outputs a span tag, if nothing else is specified. Eureka!

Get rid of 'em!

So, how do we get rid of these span tags then? We can't just go into the SharePoint code and override the RenderBeginTag and RenderEndTag of the SPRibbonCommandHandlers, and we can't change the SPRibbonCommandHandler to inherit from something better; for instance a plain ol' Control (thanks Waldek). What do we have in our toolset then? ControlAdapters of course!

After a quick analysis of the SPRibbonCommandHandlers (and the controls inheriting from it) I've found out that none of them requires to render anything (I've not tested every scenario available so I'm not giving guarantees here). I should be safe building a control adapter that makes the SPRibbonCommandHandler not rendering anything, not even a single pesky span. These controls are only present to handle different postback scenarios and handle server-side commands from the Ribbon, so they do not need to do this span-rendering-frenzia.

Using the exact same technique that I use in my SharePoint 2010 Web Parts in Action book to register ControlAdapters (get the book if your looking for the details - or download the WSP linked to at the end of this article), I created a solution that completely removed the spans.

First I created a control adapter like in the following snippet. We just override the Render method and make it do nothing.

namespace Wictor.NoSpans {
    [Guid("78e05555-17b6-44b7-95ea-3db315058b1a")]
    public class RemoveTheSpansAdapter: ControlAdapter {
        protected override void Render(System.Web.UI.HtmlTextWriter writer) {
            //base.Render(writer);
        }
    }
}

This adapter must be registered using a Browser Definition File (.browser). This file contains the original control full name and the target control like this:

<browsers>
  <browser refID="default">
    <controlAdapters>
      <adapter
        controlType="Microsoft.SharePoint.WebControls.SPRibbonCommandHandler,
Microsoft.SharePoint, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c"
adapterType="$SharePoint.Type.78e05555-17b6-44b7-95ea-3db315058b1a.FullName$,
$SharePoint.Project.AssemblyFullName$"
/> </controlAdapters> </browser> </browsers>

The .browser file must be deployed to the App_Browsers folder of the respective web application. This is done by a timer job, that copies the file from the feature to the Web Application App_Browsers file. That is; we're creating a feature that targets a Web Application. [Commercial] Full code for this is available in the book[/Commercial].

All we have to do next is deploy the control adapter, browser definition file using the WSP and start the timer job via the feature. Next time the page load we will not see the seventeen annoying empty span tags! Phew!

No more spans

Download the WSP file here to get rid of your spans...

Comments and trackbacks

#  Fantastic by Joe Capka
Screenshot from websnpr This has been a pain for many people, great job!
#  Awesome by Tobias Zimmergren
Screenshot from websnpr Wictor, that's great!
#  Thanks by Wictor
Screenshot from websnpr Thanks guys!
#  Nice by Rikard Uppström
Screenshot from websnpr Great job, been bugging me for quite some time. A pity there seems to be no way around this besides creating a control adapter..
#  dedication by Jeremy Thake
Screenshot from websnpr nice work man, knew you wouldn't be able to leave this one alone ;-)
#  Yessss by Claire
Screenshot from websnpr So glad you tackled this! SOmething that always bugs me but that I've been too lazy to figure out myself.
#  @All by Wictor
Screenshot from websnpr Thanks everyone. Sad that someone (read the product team) didnt look at the html code before the shipped it.
#  You sir... by Angel
Screenshot from websnpr are a gentleman and a scholar. Thank you!
#  Why use a SPJob? by Johan Leino
Screenshot from websnpr Just wondering Wictor, why you opt for using a timer job apposed to just doing it in the feature. Also, it wasn't totally clear that you had to "modify" the compat.browser file to make it work. Anyway, great insight!!
Make a comment on this post:
Subject:  

Your name:  
Your Url:  
Note: submissions may have to be approved before being visible, so don't submit your comment multiple times.