方法 : メモリ内のサイトマップ ノードをプログラムで変更する
更新 : 2007 年 11 月
Web サイトでは、クエリ文字列として追加される情報を含む動的 URL が頻繁に使用されます。たとえば、ニュースグループやフォーラムのサイトには、フォーラムやグループを参照する静的 URL の他に、ポストごとの動的 URL が含まれます。ポストの URL は、たとえば https://www.microsoft.com/newsgroups/ShowPost.aspx?ForumID=2\&PostID=53 という形式になります。
サイトマップを更新して各ポストの URL を一覧することは、ノードをサイトマップにプログラムで追加できないため、効率的な方法ではありません。ただし、ユーザーがポストを表示するときには、SiteMapPath コントロールを使用してルート ノードに戻るナビゲーション パスを表示し、パス内の各リンクにクエリ文字列を動的に追加してポスト、フォーラム、またはグループを識別できます。たとえば、先行ポストへのナビゲーション パスは、次のようになります。
ホーム > フォーラム リスト > ポスト リスト
ポストのサイトマップの静的 Url プロパティは、https://www.microsoft.com/newsgroups/ShowPost.aspx のように設定できます。ただし、メモリ内では SiteMapPath コントロールの URL を変更してフォーラムと特定のポストを識別できます。
次の手順と例に示すように、メモリ内のサイトマップ ノードは SiteMapResolve イベントを使用することで変更できます。
サイトマップ ノードをプログラムで変更するには
Web フォーラム ページのコードで、SiteMapResolve イベントを処理するメソッドを作成します。たとえば、次の宣言では ExpandForumPaths というメソッドが作成されます。
private SiteMapNode ExpandForumPaths(Object sender, SiteMapResolveEventArgs e)
Private Function ExpandForumPaths(ByVal sender As Object, ByVal e As SiteMapResolveEventArgs) As SiteMapNode
イベント ハンドラで、現在のノードへの参照を取得し、その複製を作成します。たとえば、ノードがニュースグループのポスティングである場合、コードは次のようになります。
SiteMapNode currentNode = SiteMap.CurrentNode.Clone(true); SiteMapNode tempNode = currentNode;
Dim currentNode As SiteMapNode = SiteMap.CurrentNode.Clone(True) Dim tempNode As SiteMapNode = currentNode
tempNode 変数は、走査できるメモリ内のサイトマップ ノードを返し、Url プロパティまたはその他のプロパティを変更します。nodeCopy 内の参照は、イベント ハンドラからの予期される戻り値が現在のノードへの参照であるため、別々に保持されます。ただし、tempNode 変数が使用されてナビゲーション構造は再帰的に上方に移動されます。
メモ : 複製されたノードは静的なサイトナビゲーション構造からは独立しているため、Url プロパティへの変更はメモリ内で保持されることも、ディスクに保存されることもありません。
現在のノードとその親ノードの Url プロパティを変更してポスト、フォーラム、およびグループ ID を一覧するクエリ文字列情報を含めます。
たとえば、次のコード例では、ID を取得する 3 つのメソッドが存在することを前提としています。
int forumGroupID = GetMostRecentForumGroupID(); int forumID = GetMostRecentForumID(forumGroupID); int postID = GetMostRecentPostID(forumID); if (0 != postID) { tempNode.Url = tempNode.Url + "?PostID=" + postID.ToString(); } if ((null != (tempNode = tempNode.ParentNode)) && (0 != forumID)) { tempNode.Url = tempNode.Url + "?ForumID=" + forumID.ToString(); } if ((null != (tempNode = tempNode.ParentNode)) && (0 != forumGroupID)) { tempNode.Url = tempNode.Url + "?ForumGroupID=" + forumGroupID.ToString(); }
Dim forumGroupID As Integer = GetMostRecentForumGroupID() Dim forumID As Integer = GetMostRecentForumID(forumGroupID) Dim postID As Integer = GetMostRecentPostID(forumID) If Not (0 = postID) Then tempNode.Url = tempNode.Url & "?PostID=" & postID.ToString() End If tempNode = tempNode.ParentNode If Not (0 = forumID) And Not (Nothing = tempNode) Then tempNode.Url = tempNode.Url & "?ForumID=" & forumID.ToString() End If tempNode = tempNode.ParentNode If Not (0 = ForumGroupID) And Not (Nothing = tempNode) Then tempNode.Url = tempNode.Url & "?ForumGroupID=" & forumGroupID.ToString() End If
メモ : if ステートメントを使用すると、グループ、フォーラム、およびポスト ID を入手できる場合のみ、クエリ文字列が既存のサイトマップにだけ追加されます。
次のコード行を使用することで複製されたノードを返します。
return currentNode;
Return currentNode
イベント ハンドラを Page_Load メソッドに登録します。たとえば、コードは次のようになります。
SiteMap.SiteMapResolve += new SiteMapResolveEventHandler(this.ExpandForumPaths);
AddHandler SiteMap.SiteMapResolve, AddressOf Me.ExpandForumPaths
メモ : SiteMapResolve イベントは、SiteMapPath コントロールがナビゲーション構造を表示している場合などに、サイトマップ プロバイダが CurrentNode プロパティにアクセスすると発生します。
SiteMapPath コントロールを Web フォーム ページに追加して、ナビゲーション構造を表示します。SiteMapPath コントロールは次のようになります。
<asp:SiteMapPath id="SiteMapPath1" runat="server" RenderCurrentNodeAsLink="true" />
サイトマップ ファイルに Web フォーム ページのノードが存在することを確認します。たとえば、Web フォーム ページの名前が ShowPost.aspx である場合、Web.sitemap ファイルは次のようになります。
<?xml version="1.0" encoding="utf-8" ?> <siteMap> <siteMapNode title="Forum Group" description="Forum Group List" url="default.aspx"> <siteMapNode title="Forum" description="Forum List" url="ShowForum.aspx"> <siteMapNode title="Post" description="Post List" url="ShowPost.aspx" /> </siteMapNode> </siteMapNode> </siteMap>
使用例
ASP.NET Web ページ上の SiteMapResolve イベントを処理して SiteMapPath コントロールによって表示されるターゲット URL を変更する方法を次のコード例に示します。この例では、現在のページはオンラインの掲示板やフォーラム内のポスト ページです。よりわかりやすいサイト ナビゲーションを表示するために、SiteMapPath コントロールによって表示されるノードの URL にコンテキストに該当するクエリ文字列が追加されています。次のコードを使用してコントロールを表示します。
<asp:SiteMapPath
id="SiteMapPath1"
runat="server"
RenderCurrentNodeAsLink="true" />
<asp:SiteMapPath
id="SiteMapPath1"
runat="server"
RenderCurrentNodeAsLink="true" />
このコード例を実行する際は、SiteMapPath コントロールのリンク上にカーソルを置いて、URL が変更されるようすを確認します。
この例では、Web.sitemap ファイルに SiteMapNode 項目は追加されないため、Web.sitemap は手動で編集するしかありません。
メモ : |
---|
CurrentNode プロパティには、SiteMapResolveEventHandler 内からアクセスすると安全です。この場合、ASP.NET サイト ナビゲーション構造によって無限の再帰が回避されます。 |
この例は、既に有効なサイトマップ ファイルが作成されていて、現在のページがそのサイトマップ構造内で 3 ノード以上の深さにあることを前提にしています。サイトマップの作成の詳細については、「ASP.NET サイト マップ」を参照してください。
Private Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
' The ExpandForumPaths method is called to handle
' the SiteMapResolve event.
AddHandler SiteMap.SiteMapResolve, AddressOf Me.ExpandForumPaths
End Sub
Private Function ExpandForumPaths(ByVal sender As Object, ByVal e As SiteMapResolveEventArgs) As SiteMapNode
' The current node represents a Post page in a bulletin board forum.
' Clone the current node and all of its relevant parents. This
' returns a site map node that a developer can then
' walk, modifying each node.Url property in turn.
' Since the cloned nodes are separate from the underlying
' site navigation structure, the fixups that are made do not
' effect the overall site navigation structure.
Dim currentNode As SiteMapNode = SiteMap.CurrentNode.Clone(True)
Dim tempNode As SiteMapNode = currentNode
' Obtain the recent IDs.
Dim forumGroupID As Integer = GetMostRecentForumGroupID()
Dim forumID As Integer = GetMostRecentForumID(forumGroupID)
Dim postID As Integer = GetMostRecentPostID(forumID)
' The current node, and its parents, can be modified to include
' dynamic querystring information relevant to the currently
' executing request.
If Not (0 = postID) Then
tempNode.Url = tempNode.Url & "?PostID=" & postID.ToString()
End If
tempNode = tempNode.ParentNode
If Not (0 = forumID) And Not (tempNode Is Nothing) Then
tempNode.Url = tempNode.Url & "?ForumID=" & forumID.ToString()
End If
tempNode = tempNode.ParentNode
If Not (0 = ForumGroupID) And Not (tempNode Is Nothing) Then
tempNode.Url = tempNode.Url & "?ForumGroupID=" & forumGroupID.ToString()
End If
Return currentNode
End Function
...
' These methods are just placeholders for the example.
' One option is to use the HttpContext or e.Content object
' to obtain the ID.
Private Function GetMostRecentForumGroupID() As Integer
Return 24
End Function
Private Function GetMostRecentForumID(ByVal forumGroupId As Integer) As Integer
Return 128
End Function
Private Function GetMostRecentPostID(ByVal forumId As Integer) As Integer
Return 317424
End Function
private void Page_Load(object sender, EventArgs e)
{
// The ExpandForumPaths method is called to handle
// the SiteMapResolve event.
SiteMap.SiteMapResolve +=
new SiteMapResolveEventHandler(this.ExpandForumPaths);
}
private SiteMapNode ExpandForumPaths(Object sender, SiteMapResolveEventArgs e)
{
// The current node represents a Post page in a bulletin board forum.
// Clone the current node and all of its relevant parents. This
// returns a site map node that a developer can then
// walk, modifying each node.Url property in turn.
// Since the cloned nodes are separate from the underlying
// site navigation structure, the fixups that are made do not
// effect the overall site navigation structure.
SiteMapNode currentNode = SiteMap.CurrentNode.Clone(true);
SiteMapNode tempNode = currentNode;
// Obtain the recent IDs.
int forumGroupID = GetMostRecentForumGroupID();
int forumID = GetMostRecentForumID(forumGroupID);
int postID = GetMostRecentPostID(forumID);
// The current node, and its parents, can be modified to include
// dynamic querystring information relevant to the currently
// executing request.
if (0 != postID)
{
tempNode.Url = tempNode.Url + "?PostID=" + postID.ToString();
}
if ((null != (tempNode = tempNode.ParentNode)) &&
(0 != forumID))
{
tempNode.Url = tempNode.Url + "?ForumID=" + forumID.ToString();
}
if ((null != (tempNode = tempNode.ParentNode)) &&
(0 != forumGroupID))
{
tempNode.Url = tempNode.Url + "?ForumGroupID=" + forumGroupID.ToString();
}
return currentNode;
}
...
// These methods are just placeholders for the example.
// One option is to use the HttpContext or e.Content object
// to obtain the ID.
private int GetMostRecentForumGroupID()
{
return 24;
}
private int GetMostRecentForumID(int forumGroupId)
{
return 128;
}
private int GetMostRecentPostID(int forumId)
{
return 317424;
}
セキュリティ
クエリ文字列およびフォーム データの操作で重要になるのは、渡されるデータを検証することです。ASP.NET には、エラーをチェックし、さらに必要に応じてユーザーにメッセージを表示するための使いやすく強力な方法を提供する、検証コントロールのセットが用意されています。前述の例ではサイトマップ ノードを変更するタスクに重点を置いたため、検証コントロールは使用していません。コードに検証を追加する方法については、「検証 ASP.NET コントロール」を参照してください。
参照
概念
ASP.NET のマスター ページとコンテンツ ページのイベント