はじめに
ASP.NET 1.0の特徴の1つに、「アダプティブレンダリング」機能がありました。この機能のお陰で、ASP.NET Webページでレンダリングされるマークアップが、アクセス側のブラウザにとって適したものになります。要するに、ASP.NETページにアクセスすると、そのWebコントロールがマークアップにレンダリングされ、ブラウザに送られて表示されるのです。しかし、Webコントロールによって生成されるマークアップは、ページにアクセスするときに使用するブラウザに依存します。「アップレベル」ブラウザでアクセスすると、ASP.NET WebコントロールはHTML 4.0準拠のマークアップをレンダリングします。一方、「ダウンレベル」ブラウザの場合、WebコントロールはHTML 3.2準拠のマークアップをレンダリングします。ASP.NET 1.xでは、「machine.config」または「web.config」内の<browserCaps>
要素を通じて、ブラウザに「アップレベル」または「ダウンレベル」のラベルが付けられました(ASP.NET 1.xの1つの欠点は、既定で、IE 4.0以上だけが「アップレベル」とマークされることでした。このため、FireFoxやOperaなどの最新のブラウザが、ダウンレベルとして認識されてしまいました)。ASP.NET 1.xのアダプティブレンダリング機能の詳細については、「A Look at ASP.NET's Adaptive Rendering」を参照してください。
ASP.NET 2.0は、ASP.NET 1.xと同様のアダプティブレンダリング機能を備えていますが、ブラウザの機能は、<browserCaps>
要素ではなく、ブラウザ定義ファイルで決定されます(<browserCaps>
は、下位互換性のためにASP.NET 2.0でも引き続きサポートされていますが、将来にわたってのサポートは保証されていないため、使用しない方が良いでしょう)。ASP.NET 2.0のレンダリングフレームワークは、アダプティブレンダリングに加えて、「コントロールアダプタ」を使って構成することもできます。コントロールアダプタはオプションのクラスです。これが存在し、正しく構成されている場合は、コントロールの既定のレンダリングロジックではなく、このコントロールアダプタを使ってWebコントロールがレンダリングされます。つまり、コントロールアダプタを使用することで、Webコントロールの核となる機能を利用できるだけでなく、発行されるマークアップを完全にカスタマイズできます。これは、すべてのブラウザの既定のレンダリングを変更したい場合や、携帯電話やポータブルデバイスなど、特定のユーザーエージェントに対してカスタマイズされたレンダリングを提供する必要がある場合に便利です。
「ASP.NET 2.0 CSS Friendly Control Adapters」には、ASP.NET 2.0のコントロールアダプタの機能を理解する上で参考になる例が示されています。Microsoftが提供する無料のこのコントロールアダプタセットは、優れたCSSの方法を使って、さまざまな組み込みのASP.NETコントロールをレンダリングする、コントロールアダプタのセットを提供します。例えばMenu Webコントロールは、既定ではHTMLの<table>
としてレンダリングされます。しかし、コントロールアダプタでは、MenuはCSSのポジショニング機能を使用する「順序なしリスト」としてレンダリングされ、適切にメニューが表示されます。さらに、CSSコントロールアダプタでは、コントロールレベルのスタイル設定(レンダリング後のマークアップ内でインラインのstyle
要素としてレンダリングされるもの)は無視されます。代わりに、そのスタイル情報を分離して、CSSクラスとして指定することが要求されます。
Menuコントロールのコントロールアダプタに加えて、CSS Friendly Control Adaptersには、TreeView、GridView、DataList、 DetailsView、Login、CreateUserWizardなど、各種コントロールのアダプタが含まれています。この記事では、CSS Friendly Control Adaptersの概要を説明したうえで、Webサイトのマークアップを整理し、向上する方法について説明します。
コントロールアダプタの概要
ユーザーがASP.NET Webページにアクセスするとき、そのASP.NETページが最終的に目標とするのは、ページのコンテンツを、要求元のクライアントに返送できるマークアップとしてレンダリングすることです。ASP.NETページは、コントロールツリー(Webコントロールと静的なHTMLコンテンツ)の中を移動して、基本的に「自分自身をレンダリングせよ」という指示を出すことによって、レンダリングされたコンテンツを生成します。各コントロールは素直に自身をレンダリングし、レンダリング後のマークアップをページに返します。このようなレンダリング結果が寄せ集められて、要求元のクライアントに送り返されます。
ASP.NET 2.0 Webコントロールが自身をレンダリングする場合は、いったん処理を停止して、自分が使用できるアダプタがないかどうかを探します。コントロールアダプタは、ControlAdapter
クラスから派生するクラスとして実装されており、BeginRender()
、Render()
、RenderChildren()
、EndRender()
など、レンダリング関連の重要なメソッドを備えています。レンダリングされるWebコントロールがコントロールアダプタを持たない場合は、レンダリングが内部で処理されます(つまり、外部のコントロールアダプタがレンダリングを処理するのではなく、既定のレンダリングロジックが使用されます)。コントロールアダプタを使用するかどうかは、ブラウザ定義ファイル内の設定によって決まります。このファイルには、どのWebコントロールがどのブラウザに対してコントロールアダプタを使用するかについての指示が含まれています。
ASP.NET Webアプリケーションでコントロールアダプタを使用するには、次の2つの手順を実行する必要があります。
- コントロールアダプタを作成(またはダウンロード)します。繰り返しになりますが、これは、直接的または間接的に
ControlAdapter
基本クラスから派生するクラスに過ぎません。.NET Frameworkには、PageAdapter
、WebControlAdapter
、DataBoundControlAdapter
など、ControlAdapter
クラスを展開したいくつかのクラスが既に含まれています(これらのクラスの多くは、コントロールアダプタ構築時の派生クラスです)。 - ブラウザ定義ファイルを構成または作成して、特定のWebコントロールおよび特定のユーザーエージェントに対してコントロールアダプタを使用することを指定します。ブラウザ定義ファイルの拡張子は「.browser」です。既定のブラウザ定義ファイルは、「%WINDIR%\Microsoft.NET\Framework\v2.0.50727\CONFIG\Browsers」にあります。この情報は、「App_Browsers」フォルダに.browserファイルを追加することによって、特定のWebアプリケーション用にカスタマイズできます。
この記事では、独自のコントロールアダプタは作成せずに、MicrosoftのCSS Friendly Control Adaptersをダウンロードして使用します。
ASP.NET Webコントロールの既定のマークアップの改良
カスケーディングスタイルシート(CSS)はWeb開発で使用される手法であり、特定のHTML要素、HTML要素のクラス、または特定のHTML要素タイプのすべてのインスタンスのプレゼンテーション設定を指定できます(すべての<div>
要素の表示設定の指定など)。特定のHTML要素のプレゼンテーション設定を指定するには、要素のstyle
属性を使用します。例えば、以下のマークアップでは、段落要素の背景色が緑色であることを指定しています。
<p style="background-color: Green;"> This has a green background! </p>
しかしながら、理想的には、プレゼンテーション情報はCSSクラスを使って指定します。CSSクラスは、要素のクラスのプレゼンテーションスタイルを定義するものであり、<style>
要素で、または、<link>
要素を介してページに関連付けられる外部のCSSファイルを通じて定義されます。定義されたクラスは、要素のclass
属性を通じて特定のHTML要素に関連付けられます。以下のマークアップでは、テキストを赤色の太字フォントで表示する.Warning
という名前のクラスを追加しています。その後の<span>
要素はクラスに関連付けられており、その結果、ブラウザを通じて表示される場合、赤色の太字のテキストとして表示されます。
<style type="text/css"> .Warning { font-weight: bold; color: red; } </style> <span class="Warning"> Danger! Danger! </span>
CSSクラスを使用する方法は、2つの理由で、インラインスタイルよりも優れています。第一に、プレゼンテーション情報を1箇所(<style>
要素または個別のCSSファイル)に指定し、それをページ内の複数の場所に適用できるため、ページ全体のサイズが削減されます。インラインスタイルだけを使用するのであれば、プレゼンテーション情報を各コントロールに対して繰り返し適用しなければなりません。第二に、プレゼンテーション情報が集中化されていることにより、変更が必要な設定が1箇所しかないため、サイトの再設計やプレゼンテーションの変更も非常に簡単です。
残念ながら、ASP.NETのWebコントロールのスタイル関連のプロパティは、インラインスタイルとしてレンダリングされます。つまり、Label Webコントロールをページに追加し、そのForeColor
プロパティを「Red」に設定した場合、Labelは次のようなマークアップをレンダリングします。
<span style="color: red;">Label Text</span>
しかし、一部のコントロールはインテリジェントであり、インラインスタイルではなくクラスを使用できます。例えば、Menuコントロールは、そのスタイル関連のプロパティをレンダリングするときに、インラインスタイルではなくクラスを使用します。さらに、すべてのWebコントロールはCssClass
プロパティを備えており、その使用が推奨されます。しかし、インラインプロパティの使用は魅力的であり、多くの開発者が実際に使用しています。
また、多くのASP.NET Webコントロールは、レンダリングの位置を決める際に、標準のブロック要素(<div>
など)とCSSを通じた位置指定を使用するのではなく、HTMLの<table>
を使用しています。HTMLの<table>
は、表形式のデータを格納するために設計されたものであり、レイアウト目的で使用するものではありません。しかし、MenusやTreeViewsをはじめとする組み込みのASP.NET Webコントロールでは、これがレイアウト目的で使用されています。
ただし、この動作は、コントロールアダプタでオーバーライドできます。コントロールアダプタはゼロから作成することもできますが、Microsoftが提供するASP.NET 2.0 CSS Friendly Control Adaptersをダウンロードすれば、最小限の手間でこれを自分のASP.NET Webアプリケーションにプラグインできます。コントロールアダプタをいったんインストールすると、インラインスタイル属性はレンダリングされず(CSSクラスを使用する必要があります)、MenuやTreeViewなどのコントロールの<table>
方式レイアウトが、CSS方式に置換されます。
<table>
は、GridViewにデータをリストするなど、表形式のデータを表示するために使用すべきであり、ページレイアウトの指定(例えば<table>
を使って3列×2行のレイアウトをページに配置するなど)に使用すべきではありません。理想的には、ページレイアウトにはCSS方式を使用すべきです。しかし、言行不一致ですが、筆者はしばしばレイアウト目的で<table>
を使用しています。一番の理由は、CSSで行うより<table>
でコンテンツをレイアウトする方法の方がよくわかっているからです。概して筆者は、<table>
方式でレイアウトするか、CSS方式でレイアウトするかという問題に、あまり興味がありません。理想的にはCSSを使用すべきですが、テーブルを完全に排し、すべてをCSSで実現するために必要な多くの知識を学ぶことに作業時間のかなりの部分(何だかんだといって最終段階における95%程度)を費やすほど熱狂的な支持者ではありません(幸い、CSS Friendly Control Adaptersなどのツールは、学習曲線を心配することなく、この移行を実現してくれます)。この問題に関する筆者の無関心な態度とは対照的に、一部の人はどちらかの方法を強硬に主張しており、Web上にも、一方の方法を賞賛し、他方の方法を非難する記事やエッセイが多数存在します。書き方に工夫があって特に面白かったのは、Bill MerikallioとAdam Prattによる「Why tables for layout is stupid」です。2つの方法のプラス面とマイナス面をバランスよく述べたものとしては、「Tables vs. CSS: PROS and CONS」があります。