Programming Microsoft ASP.NET 4 - Dino Esposito [123]
Adaptive Rendering
ASP.NET controls are like HTML factories that accept external parameters and produce chunks of markup. As a developer, you can select and filter any parameters being assigned to control properties. As a developer, though, you can hardly control what the component does to generate the markup. The bad effect is that you end up with an HTML markup that might work differently on different browsers and different browser configurations. When this happens, though, the worst thing is that you have no way to fix it—the HTML is out of your reach. Before ASP.NET 4, adaptive rendering was the common way to address this problem.
Adaptive rendering is the process that enables controls to generate different markup for individual browsers. This result is obtained by delegating the generation of the markup to an external component—the adapter. When each control is about to render, it figures out its current adapter and hands the request over to that adapter. Nicely enough, a control adapter is a configurable component that you can declaratively unplug in any application to roll your own.
The selected adapter depends on the current browser. The adapter for a control is resolved by looking at the browser capabilities as configured in the ASP.NET browser database. If the browser record includes an adapter class for a given control, the class is instantiated and used. Otherwise, the default adapter for the control is used, which is an instance of the ControlAdapter class. The ControlAdapter class is a generic adapter and simply generates the markup for a control by calling the rendering methods on the control itself.
Note
The ASP.NET database used for storing browser information is not a real database. It is, instead, a list of text files with a .browser extension located under the ASP.NET installation folder on the Web server. The exact path is the following:
%WINDOWS%\Microsoft.NET\Framework\[version]\CONFIG\Browsers
The data located in this folder is used to return browser capabilities.
A control holds a reference to the mapped adapter instance through the (protected) Adapter property. Each control has an associated adapter unless it is a composite control that defers to its child controls for rendering.
All ASP.NET controls have an entry point into the rendering engine in the Render method. Here’s the method’s signature:
protected virtual void Render(HtmlTextWriter writer)
{
...
}
The Render method ends up calling into an internal method whose implementation is nearly identical to the following pseudocode:
void RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
{
if (adapter != null)
{
adapter.BeginRender(writer);
adapter.Render(writer);
adapter.EndRender(writer);
}
else
{
this.Render(writer);
}
}
As you can see, if defined, a control adapter is used to generate the markup for the control. The adapter can be declaratively specified and is an external component that can be made to measure for your needs. Using an adapter to alter the markup of a given class of controls is an unobtrusive option that doesn’t require any changes to existing pages using the control. It only requires you to add a browser definition file.
Browser definition files have a .browser extension and contain definitions that apply to a specific browser. At run time, ASP.NET determines the browser being used, uses the configuration file to determine the capabilities of the browser, and based on that figures out how to render markup to that browser. Here’s a snippet that illustrates how to register a control adapter