#5:「パンくずリスト」を表示する
ASP.NET 2.0では、SiteMapPathコントロールを使うことでパンくずリストを非常に簡単に表示できます。この機能を利用して、さらに興味深い問題を解決することができます。つまり、パンくずリスト中の一部のページを非表示にすることができます。
パンくずリスト中の一部のページを非表示にするという機能は、状況によっては非常に便利ですが、実装するのは厄介です。例えば、一連のページを機能的にはホームページの子と同じように動作させたいが、見た目はトップレベルページではなく第3レベルページのように表示したいとします。このサイトマップは次のようになっています。
- Home(ルート)
- Home(トップレベルページ)
- Privacy Policy
- Site Map
- Articles
- Article #1
- Article #1
- Solutions
- ……
- ……
この場合、「Privacy Policy」ページと「Article #1」ページでは、パンくずリストの表示アプローチを変えなければなりません。例えば、「Article #1」ページではパンくずリストをHome > Articles > Article #1として表示しなければなりません。つまり、ルートの「Home」ページと、「Article #1」の親に当たるトップレベルページを表示します。一方、「Privacy Policy」ページではパンくずリストをHome > Privacy Policyとして表示しなければなりません。しかし、ルートの「Home」ページと、「Privacy Policy」ページの親に当たるトップレベルページを表示したのでは、「Home」を2回表示することになってします。そこで、パンくずリストからどちらかの「Home」を隠すための手段が必要になります。
この問題は3つのステップで解決することができます。まず、目的のページでSiteMapPathテンプレートを使用します。
<asp:SiteMapPath ID="smp" runat="server" PathSeparator=""> <RootNodeTemplate> <a href="/Default.aspx" >Home</a> </RootNodeTemplate> <NodeTemplate> <%# (IsSiteMapNodeVisible(Container.SiteMapNode) ? Eval("Url," " // <a href=\"{0}\">") + Eval("Title," "{0}</a>") : "") %> </NodeTemplate> <CurrentNodeTemplate> <%# Eval("Title," " // {0}")%> </CurrentNodeTemplate> </asp:SiteMapPath>
次に、「Web.sitemap」内のsiteMapNode要素にvisible="false"という属性を追加します。
<siteMapNode url="/" title="Home"> <siteMapNode url="~/Default.aspx" title="Home" visible="false" /> ...
さらに、このvisibleプロパティを参照するIsSiteMapNodeVisible()関数を分離コードに追加します。
protected bool IsSiteMapNodeVisible(SiteMapNode node) { // pages that don't contain an item in Web.sitemap return null if (node == null) return true; // most pages won't contain the visible attribute else if (node["visible"] == null) return true; else // return true unless visible is set to "false" return !node["Visible"].Equals("false"); }
先ほどのソリューションについて注意すべき点が2つあります。1つ目は、「Web.sitemap」は2つの異なるURL名を使って「Default.aspx」を参照していることです。この点は重要です。こうしないと.NET Frameworkは次のようなエラーを返します。
Multiple nodes with the same URL 'Default.aspx' were found. XmlSiteMapProvider requires that sitemap nodes have unique URLs.
.NET Frameworkが一意のURLを要求するのは、バックグラウンドでメモリ内のDictionaryオブジェクトにSiteMapNodesオブジェクトを格納するためです。この必要条件に対応するには、URLにパラメータを追加するという方法があります(例えば、Default.aspx?1、Default.aspx?2など)。
2つ目は、パンくずリストを非表示にする予定がある場合はPathSeparatorを使用できないということです。PathSeparator属性またはPathSeparatorTemplateプロパティのいずれかを使ってパス区切り文字を設定すると、非表示のパンくずリストについても区切り文字が表示されるため、結果的に区切り文字が二重に表示されてしまいます。
先ほどのソリューションでは、NodeTemplateおよびCurrentNodeTemplateに「//」というパス区切り文字を手作業で書き込むことでこの問題に対応しています。こうするとNodeStyle-Font-Bold型の属性の意味がなくなることに注意してください。なぜなら、これらの属性がパンくずリストのコンテンツだけでなく区切り文字にも適用されるようになるためです。従って、NodeTemplateは定義されている書式設定をまんべんなく適用します。
パンくずリストの一部を隠すというひねりを加えたとしても、ASP.NET 2.0のパンくずリストのソリューションはカスタムソリューションと比べれば非常に単純です。そして何より素晴らしいのは、SiteMapPathテンプレートとカスタム属性を使ってアプローチを簡単に拡張できるという点です。
#6:メタデータを中央に集める
ASP.NET 2.0では、任意のページ情報を1か所にまとめて保管する機能によって多くの問題を解決することができます。例えば、メタキーワードとメタ説明を各ページに分散させるのではなく「Web.sitemap」でまとめて管理すると簡潔になります。新しいアプローチでは、このようなメタデータをHTMLページに簡単に挿入することができます。
<head> <title><%# mstrTitle %></title> <meta name="description" content="<%# mstrMetaDescription %>" /> <meta name="keywords" content="<%# mstrMetaKeywords %>" />
後は、分離コード内でいくつかのprotectedプロパティを宣言して設定するだけです。
protected string mstrMetaKeywords = ""; protected string mstrMetaDescription = ""; protected string mstrTitle = ""; protected void Page_Load(object sender, EventArgs e) { if (SiteMap.CurrentNode != null) { if (SiteMap.CurrentNode["metaKeywords"] != null) mstrMetaKeywords = SiteMap.CurrentNode["metaKeywords"]; mstrMetaDescription = SiteMap.CurrentNode.Description; mstrTitle = SiteMap.CurrentNode.Title; } ... if (!Page.IsPostBack) Page.DataBind(); }
CurrentNodeプロパティまたはカスタム定義のSiteMapNode属性がnullかどうかを確認することを忘れないでください。最後に、metaKeywords属性とdescription属性を「Web.sitemap」ファイルに追加します。
<siteMapNode
url="~/SiteMap.aspx"
title="Site Map"
metaKeywords="Site Map"
description="The Site Map provides links to every
page on the site organized in a logical hierarchy." />
このアプローチにより、内外の検索エンジンで使用されるページレベルのメタデータを維持することが非常に簡単になります。この手法とマスタページを組み合わせれば、Web管理者の仕事がなくなるかもしれません。
#7:サイトマップの簡潔さ
SiteMapDataSourceとTreeViewをWebフォームに追加し、Treeview.DataSourceIDプロパティをSiteMapDataSourceに設定するだけで、実際に機能するサイトマップをサイトに追加することができます。ルートノードを非表示にするには、SiteMapDataSource.ShowStartingNodeプロパティをfalseに設定するだけです。ShowExpandCollapseプロパティをfalseに設定しShowLinesをtrueに設定すれば、TreeViewはもう少し見やすくなります。図3を参照してください。
パート2もお楽しみに!
本稿では、開発者がよく直面する状況に照らして、7つの問題とそのソリューションを基本的なASP.NET 2.0サイトナビゲーションの手法を使って説明しました。パート2では、さらに2つの問題とソリューションを紹介し、許可されていないページの非表示、動的コンテンツを取り込むためのサイトマッププロバイダモデルの拡張、ASP.NET 2.0の新しいSqlCacheDependencyクラスを使った動的コンテンツのキャッシングなど、より高度な手法を解説します。

