サイトマップファイル(例えばWeb.sitemap)に以下のように記述した場合、クエリー文字列が異なると違うページと見なされ、SiteMapPathコントロールなどがサイトマップファイル内から一致するパスを見つけられず、何も表示されなくなってしまう。
<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode url="Default.aspx" title="デフォルトページ" description="">
<siteMapNode url="SiteMapPathPaging.aspx?id=12345" title="SiteMapPathPaging" description="SiteMapPathのテスト" />
</siteMapNode>
</siteMap>
ここで、SiteMapPathPaging.aspx?page=2&id=12345などとするとurlが一致せず、SiteMapPathが表示されない。ちなみに、
<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode url="Default.aspx" title="デフォルトページ" description="">
<siteMapNode url="SiteMapPathPaging.aspx" title="SiteMapPathPaging" description="SiteMapPathのテスト" />
</siteMapNode>
</siteMap>
とクエリー文字列を付加しないで定義した場合、実際のページにクエリー文字列が含まれていても、それを省いて探してくれるようで、SiteMapPathコントロールが表示される。この動作はよくあるパターンなので、この仕様でOKだと思う。
問題なのは最初のパターンである。この場合は、独自のSiteMapPathプロバイダを定義してしまう方法がある。それを以下に示す。
App_Code内に、以下のクラスを作成する。
public class TestSiteMapProvider : XmlSiteMapProvider
{
public override System.Web.SiteMapNode FindSiteMapNode(System.Web.HttpContext context)
{
SiteMapNode node = base.FindSiteMapNode(context);
if (node == null)
{
if (context == null)
{
return null;
}
string [] queryString = ((Page)(context.CurrentHandler)).ClientQueryString.Split('&');
string pageUrl;
if (queryString.Length > 1)
pageUrl = HttpUtility.UrlDecode(context.Request.Path + "?" + queryString[1]);
else
pageUrl = HttpUtility.UrlDecode(context.Request.Path + "?" + queryString[0]);
node = base.FindSiteMapNode(pageUrl);
}
return node;
}
}
上のコードは何をやっているかというと、簡単に言えば、余計なクエリー文字列を除いて、サイトマップファイル内をもう一度検索しに行っている。
例えば、
SiteMapPathPaging.aspx?page=2&id=12345
で見つからなければ、
SiteMapPathPaging.aspx?id=12345
で、もう一度探しに行ってる。ちなみにこのコードは手抜きなので、実際にはもう少しきちんと書いた方が良いw
上記の独自のSiteMapProviderは、web.configに追加する必要がある。以下のような感じである。
<system.web>
<siteMap enabled="true">
<providers>
<add name="TestSiteMapProvider"
type="TestSiteMapProvider" siteMapFile="Web.sitemap" />
</providers>
</siteMap>
</system.web>
そして、SiteMapPathコントロールのSiteMapProviderに、TestSiteMapProviderを指定してあげれば全て完了である。
以上で、サイトマップファイルのurlに SiteMapPathPaging.aspx?id=12345 と書いていても、
SiteMapPathPaging.aspx?page=2&id=12345 のようなurlを持つページでも、SiteMapPathコントロールが表示されるようになる。
(参考)
SiteMapProvider and spaces in querystrings
http://blogs.msdn.com/dannychen/archive/2006/03/08/545793.aspx
[ASP.NET]サイト内に複数のサイトマップ・ファイルを設置するには?[2.0のみ、C#、VB]
http://www.atmarkit.co.jp/fdotnet/dotnettips/510asplocalizesitemap2/asplocalizesitemap2.html