Thursday, April 1, 2010

Removing the default span from a Custom Web Server Control

If you have ever developed a custom Web Server Control for ASP.NET, you may have realized that the Web Server Control automatically encapsulates your control inside a span tag:


This is because the WebControl's constructor sets HtmlTextWriterTag.Span as the default begin tag:

protected WebControl() : this(HtmlTextWriterTag.Span) { 

}

Fixing the issue

To fix this, all you need to do is override the Render method in your Control class , as follows:

protected override void Render(HtmlTextWriter writer)
{
    RenderContents(writer);
}

That way, you will be suppressing the outer span tag from being rendered.

Further Explanation

The following is the implementation of the Render method inside the WebControl class:

protected internal override void Render(HtmlTextWriter writer)
{
    this.RenderBeginTag(writer);
    this.RenderContents(writer);
    this.RenderEndTag(writer);
}

As you can see, it's calling the RenderBeginTag method of the same WebControl class:

public virtual void RenderBeginTag(HtmlTextWriter writer)
{
    this.AddAttributesToRender(writer);
    HtmlTextWriterTag tagKey = this.TagKey;
    if (tagKey != HtmlTextWriterTag.Unknown)
    {
        writer.RenderBeginTag(tagKey);
    }
    else
    {
        writer.RenderBeginTag(this.TagName);
    }
}

The RenderBeginTag is rendering tagKey, which is set in the constructor we saw earlier on:

private HtmlTextWriterTag tagKey;

protected WebControl() : this(HtmlTextWriterTag.Span) { }
public WebControl(HtmlTextWriterTag tag)
{
    this.tagKey = tag;
}

Therefore, by overriding the Render method in our WebControl subclass to only call the RenderContents method, we will be bypassing the following methods that render the span tag: RenderBeginTag and RenderEndTag.

protected override void Render(HtmlTextWriter writer)
{
    RenderContents(writer);

    /* instead of: 

    Render(HtmlTextWriter writer)
    {
        this.RenderBeginTag(writer);
        this.RenderContents(writer);
        this.RenderEndTag(writer);
    }

     */
}