マスター ページの URL (C#)
マスター ページ ファイルがコンテンツ ページとは異なる相対ディレクトリに存在することにより、マスター ページ内の URL が壊れる可能性があることについて説明します。 宣言構文で ~ を介して URL をリベースする方法と、ResolveUrl と ResolveClientUrl をプログラムで使用する方法について説明します。 (また、次を参照してください。
はじめに
これまでに見てきたすべての例では、マスター ページとコンテンツ ページは同じフォルダー (Web サイトのルート フォルダー) に配置されていました。 しかし、マスター ページとコンテンツ ページが同じフォルダー内に存在すべき理由はありません。 サブフォルダーにコンテンツ ページを作成しても問題ありません。 同様に、~/MasterPages/
フォルダーを作成して、そこにサイトのマスター ページを配置することもできます。
マスター ページとコンテンツ ページを異なるフォルダーに配置する場合の潜在的な問題の 1 つは、URL の破損です。 マスター ページ内のハイパーリンク、画像、またはその他の要素に相対 URL が含まれている場合、別のフォルダー内のコンテンツ ページのリンクは無効になります。 このチュートリアルでは、この問題の原因と回避策について説明します。
相対 URL に関する問題
Web ページ上の URL は、それが指定するリソースの場所が Web サイトのフォルダー構造における Web ページの場所を基準とする場合に、"相対 URL" と呼ばれます。 先頭がスラッシュ (/
) やプロトコル (http://
など) で始まらない URL は、URL を含む Web ページの場所に基づいてブラウザーによって解決されるため、相対 URL です。
たとえば、ここでの Web サイトには、1 つの画像ファイル PoweredByASPNET.gif
が入った ~/Images/
フォルダーがあります。 マスター ページ ファイル Site.master
の footerContent
領域には、以下のマークアップを含む <img>
要素があります。
<div id="footerContent">
<img src="Images/PoweredByASPNET.gif" alt="Powered by ASP.NET!" />
</div>
<img>
要素内の src
属性値は、先頭が /
または http://
ではないため、相対 URL です。 つまり、src
属性値はブラウザーに対して、Images
サブフォルダー内の PoweredByASPNET.gif
という名前のファイルを探すよう指示します。
コンテンツ ページにアクセスすると、上記のマークアップがブラウザーに直接送信されます。 About.aspx
にアクセスして、ブラウザーに送信された HTML ソースを確認してみてください。 マスター ページ内のまったく同じマークアップがブラウザーに送信されていることがわかります。
<div id="footerContent">
<img src="Images/PoweredByASPNET.gif" alt="Powered by ASP.NET!" />
</div>
コンテンツ ページがルート フォルダー (About.aspx
と同様) にある場合は、ルート フォルダーに対して相対的に Images
サブフォルダーが存在するため、すべてが期待どおりに動作します。 しかし、コンテンツ ページがマスター ページと異なるフォルダーにある場合は、問題が発生します。 これを説明するために、Admin
という名前のサブフォルダーを作成します。 次に、Admin
フォルダーに Default.aspx
という名前のコンテンツ ページを追加し、新しいページを Site.master
マスター ページにバインドします。
Note
「マスター ページでタイトル、メタ タグ、その他の HTML ヘッダーを指定する」チュートリアルでは、コンテンツ ページのタイトルを (それが明示的に割り当てられていない場合に) 自動的に設定する、BasePage
という名前のカスタム ベース ページ クラスを作成しました。 この機能を利用できるように、忘れずに新しく作成されたページの分離コード クラスを BasePage
から派生させるようにしてください。
このコンテンツ ページを作成すると、ソリューション エクスプローラーは図 1 のようになります。
図 01: 新しいフォルダーと ASP.NET ページがプロジェクトに追加されました
次に、この新しい <siteMapNode>
エントリを含むように Web.sitemap
ファイルを更新します。 以下の XML は、3 つめの <siteMapNode>
要素が追加された完全な Web.sitemap
マークアップを示しています。
<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode url="~/Default.aspx" title="Home">
<siteMapNode url="~/About.aspx" title="About the Author" />
<siteMapNode url="~/MultipleContentPlaceHolders.aspx" title="Using Multiple ContentPlaceHolder Controls" />
<siteMapNode url="~/Admin/Default.aspx" title="Rebasing URLs" />
</siteMapNode>
</siteMap>
新しく作成された Default.aspx
ページには、Site.master
の 4 つの ContentPlaceHolders に対応する 4 つの Content コントロールがあります。 MainContent
ContentPlaceHolder を参照している Content コントロールに何らかのテキストを追加し、ブラウザーからページにアクセスします。 図 2 に示すように、ブラウザーは PoweredByASPNET.gif
画像ファイルを見つけることができません。 どうなっているのでしょうか?
~/Admin/Default.aspx
コンテンツ ページには、About.aspx
ページと同じ HTML が footerContent
領域に送信されます。
<div id="footerContent">
<img src="Images/PoweredByASPNET.gif" alt="Powered by ASP.NET!" />
</div>
<img>
要素の src
属性は相対 URL であるため、ブラウザーは Web ページのフォルダーの場所を基準に Images
フォルダーを探そうとします。 言い換えると、ブラウザーは画像ファイル Admin/Images/PoweredByASPNET.gif
を探しています。
図 02: PoweredByASPNET.gif
画像ファイルが見つかりません (クリックするとフルサイズの画像が表示されます)
相対 URL を絶対 URL に置き換える
相対 URL の反対は "絶対 URL" で、スラッシュ (/
) や http://
のようなプロトコルで始まります。 絶対 URL は既知の固定ポイントからのリソースの場所を指定するため、Web サイトのフォルダー構造における Web ページの場所に関係なく、同じ絶対 URL はどの Web ページでも有効です。
図 2 に示されている破損した画像を修正するには、<img>
要素の src
属性を更新して、相対 URL ではなく絶対 URL を使用するようにする必要があります。 正しい絶対 URL を判断するには、Web サイトのいずれかの Web ページにアクセスし、アドレス バーを調べます。 図 2 のアドレス バーが示すように、Web アプリケーションへの完全修飾パスは http://localhost:3908/ASPNET_MasterPages_Tutorial_04_CS/
です。 そのため、<img>
要素の src
属性を以下の 2 つの絶対 URL のいずれかに更新できます。
/ASPNET_MasterPages_Tutorial_04_CS/Images/PoweredByASPNET.gif
http://localhost:3908/ASPNET_MasterPages_Tutorial_04_CS/Images/PoweredByASPNET.gif
上記のいずれかの形式を使用して <img>
要素の src
属性を絶対 URL に更新したら、ブラウザーから ~/Admin/Default.aspx
ページにアクセスします。 今回は、ブラウザーが PoweredByASPNET.gif
画像ファイルを正しく見つけて表示します (図 3 を参照)。
図 03: PoweredByASPNET.gif
画像が表示されるようになりました (クリックするとフルサイズの画像が表示されます)
絶対 URL のハード コーディングは機能しますが、HTML が、変更される可能性のある Web サイトのサーバーやフォルダーの場所に密接に結び付いてしまいます。 http://localhost:3908/...
という形式の絶対 URL を使用することは危険です。localhost
の前のポート番号は、Visual Studio の組み込み ASP.NET 開発 Web サーバーが起動されるたびに自動的に選択されるからです。 同様に、http://localhost
の部分はローカルでテストする場合のみ有効です。 コードが運用サーバーに配置されると、URL ベースは http://www.yourserver.com
のような別のものに変更されます。 形式 /ASPNET_MasterPages_Tutorial_04_CS/...
の絶対 URL も、開発サーバーと運用サーバーでこのアプリケーション パスが異なる場合が多いため、同じく不安定です。
幸いなことに、ASP.NET には実行時に有効な相対 URL を生成するためのメソッドが用意されています。
~
と ResolveClientUrl
を使用する
ASP.NET では、絶対 URL をハード コーディングする代わりに、ページ開発者はチルダ (~
) を使用して Web アプリケーションのルートを示すことができます。 たとえば、このチュートリアルの前半では、テキスト内で ~/Admin/Default.aspx
表記を使用して Admin
フォルダー内の Default.aspx
ページを参照しました。 ~
は、Admin
フォルダーが Web アプリケーションのルートのサブフォルダーであることを示します。
Control
クラスの ResolveClientUrl
メソッドは、URL をコントロールが存在する Web ページに適した相対 URL に変更します。 たとえば、About.aspx
から ResolveClientUrl("~/Images/PoweredByASPNET.gif")
を呼び出すと、Images/PoweredByASPNET.gif
が返されます。 しかし、~/Admin/Default.aspx
から呼び出すと、../Images/PoweredByASPNET.gif
が返されます。
Note
すべての ASP.NET サーバー コントロールは Control
クラスから派生するため、すべてのサーバー コントロールが ResolveClientUrl
メソッドにアクセスできます。 Page
クラスも Control
クラスから派生するため、ASP.NET ページの分離コード クラスから直接このメソッドを使用できます。
宣言型マークアップで ~
を使用する
ASP.NET のいくつかの Web コントロールには、URL 関連のプロパティが含まれます。たとえば、HyperLink コントロールには NavigateUrl
プロパティがあり、Image コントロールには ImageUrl
プロパティがあります。 これらのコントロールは、レンダリング時に URL 関連のプロパティ値を ResolveClientUrl
に渡します。 したがって、これらのプロパティに Web アプリケーションのルートを示す ~
が含まれている場合、URL は有効な相対 URL に変更されます。
ASP.NET サーバー コントロールのみが、URL 関連のプロパティの ~
を変換することに注意してください。 <img src="~/Images/PoweredByASPNET.gif" />
のように静的 HTML マークアップに ~
がある場合、ASP.NET エンジンは ~
を残りの HTML コンテンツと共にブラウザーに送信します。 ブラウザーは、~
を URL の一部と見なします。 たとえば、ブラウザーが <img src="~/Images/PoweredByASPNET.gif" />
というマークアップを受け取った場合、画像ファイル PoweredByASPNET.gif
を含む サブフォルダー Images
が含まれた ~
というサブフォルダーが存在すると推測されます。
Site.master
の画像マークアップを修正するには、既存の <img>
要素を ASP.NET Image Web コントロールに置き換えます。 Image Web コントロールの ID
を PoweredByImage
に設定し、ImageUrl
プロパティを ~/Images/PoweredByASPNET.gif
に設定し、AlternateText
プロパティを「Powered by ASP.NET!」に設定します。
<div id="footerContent">
<asp:Image ID="PoweredByImage" runat="server" ImageUrl="~/Images/PoweredByASPNET.gif"
AlternateText="Powered by ASP.NET!" />
</div>
マスター ページにこれらの変更を行った後、再度 ~/Admin/Default.aspx
ページにアクセスします。 今回は、画像ファイル PoweredByASPNET.gif
がページ内に表示されます (図 3 を参照)。 Image Web コントロールがレンダリングされると、ResolveClientUrl
メソッドを使用して ImageUrl
プロパティ値が解決されます。 以下の HTML ソースのスニペットが示すように、~/Admin/Default.aspx
では ImageUrl
が適切な相対 URL に変換されます。
<div id="footerContent">
<img id="ctl00_PoweredByImage" src="../Images/PoweredByASPNET.gif" alt="Powered by ASP.NET!" />
</div>
Note
URL ベースの Web コントロール プロパティで使用されるだけでなく、~
は Response.Redirect
メソッドや Server.MapPath
メソッドなどを呼び出すときにも使用できます。 また、ResolveClientUrl
メソッドは、ASP.NET またはマスター ページの宣言型マークアップから直接呼び出すこともできます。
マスター ページの残りの相対 URL を修正する
マスター ページには、修正した footerContent
内の <img>
要素に加えて、注意が必要な相対 URL がもう 1 つあります。 topContent
領域には、Default.aspx
を指す「Master Pages Tutorials」というリンクが含まれています。
<div id="topContent">
<a href="Default.aspx">Master Pages Tutorials</a>
</div>
この URL は相対 URL であるため、アクセスしているコンテンツ ページのフォルダー内の Default.aspx
ページにユーザーを移動させます。 このリンクがルート フォルダー内の Default.aspx
を常に指すようにするには、~
表記を使用できるように、<a>
要素を HyperLink Web コントロールに置き換える必要があります。
<a>
要素のマークアップを削除し、その場所に HyperLink コントロールを追加します。 HyperLink コントロールの ID
を lnkHome
に設定し、NavigateUrl
プロパティを ~/Default.aspx
に設定し、Text
プロパティを「Master Pages Tutorials」に設定します。
<div id="topContent">
<asp:HyperLink ID="lnkHome" runat="server" NavigateUrl="~/Default.aspx"
Text="Master Pages Tutorials" />
</div>
これで完了です。 この時点で、マスター ページ内のすべての URL が、マスター ページとコンテンツ ページがどのフォルダーに配置されているかに関係なく、コンテンツ ページによってレンダリングされる際に適切に裏付けられます。
<head>
セクションでの URL の自動解決
「マスター ページを利用してサイト全体レイアウトを作成する」チュートリアルでは、<head>
領域内の Styles.css
ファイルに <link>
を追加しました。
<head runat="server">
<title>Untitled Page</title>
<asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder>
<link href="Styles.css" rel="stylesheet" type="text/css" />
</head>
<link>
要素の href
属性は相対的ですが、実行時に適切なパスに自動的に変換されます。 「マスター ページでタイトル、メタ タグ、その他の HTML ヘッダーを指定する」チュートリアルで説明したように、<head>
領域は実際にはサーバー側コントロールであり、これによりレンダリング時に内部コントロールの内容を変更できるようになっています。
これを確認するには、~/Admin/Default.aspx
ページに再度アクセスし、ブラウザーに送信された HTML ソースを表示します。 以下のスニペットが示すように、<link>
要素の href
属性は自動的に適切な相対 URL である ../Styles.css
に変更されています。
<head>
<title>
Default
</title>
<link href="../Styles.css" rel="stylesheet" type="text/css" />
</head>
まとめ
多くの場合、マスター ページには URL を介して指定する必要があるリンクや画像、その他の外部リソースが含まれます。 マスター ページとコンテンツ ページが同じフォルダーに存在しない可能性があるため、相対 URL の使用を控える必要があります。 ハードコーディングされた絶対 URL を使用することは可能ですが、これを行うと、絶対 URL が Web アプリケーションに密に結び付いてしまいます。 絶対 URL が変わった場合は (Web アプリケーションの移動や配置時によくあります)、必ず前に戻って絶対 URL を更新する必要があります。
理想的な方法は、チルダ (~
) を使用してアプリケーション ルートを示すことです。 URL 関連のプロパティを含む ASP.NET Web コントロールによって、~
は実行時にアプリケーション ルートにマップされます。 内部的には、Web コントロールによって Control
クラスの ResolveClientUrl
メソッドを使用して有効な相対 URL が生成されます。 このメソッドはパブリック メソッドであり、すべてのサーバー コントロール (Page
クラスを含む) から使用できるため、必要に応じて分離コード クラスからプログラムで使用できます。
プログラミングに満足!
もっと読む
この記事で説明したトピックの詳細については、次のリソースを参照してください。
作成者について
複数の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジに取り組んでいます。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の著書は、『Sams Teach Yourself ASP.NET 3.5 in 24 Hours』です。 Mitchell 氏には、mitchell@4GuysFromRolla.com から、または http://ScottOnWriting.NET で彼のブログを介して連絡できます。
特別な感謝
今後の MSDN の記事を確認することに関心がありますか? ご希望の場合は、mitchell@4GuysFromRolla.com までメッセージをお送りください。