預設 XML SiteMap 適用靜態結構。動態網站 (如分類/產品階層) 需從資料庫/BLL 即時建構。ASP.NET SiteMap 採 Provider Model,可自訂 SiteMapProvider 從 BLL 取得資料。
public class DynamicSiteMapProvider : StaticSiteMapProvider
{
private SiteMapNode rootNode;
private readonly object lockObj = new object();
public override SiteMapNode RootNode
{
get { return BuildSiteMap(); }
}
protected override SiteMapNode GetRootNodeCore()
{
return BuildSiteMap();
}
private SiteMapNode BuildSiteMap()
{
lock (lockObj)
{
if (rootNode != null) return rootNode;
rootNode = new SiteMapNode(this, "Root", "~/", "首頁");
// 從 BLL 取得分類
var categories = CategoriesBLL.GetCategories();
foreach (var cat in categories)
{
SiteMapNode catNode = new SiteMapNode(this,
"Cat_" + cat.CategoryID,
"~/ProductsByCategory.aspx?CategoryID=" + cat.CategoryID,
cat.CategoryName);
rootNode.ChildNodes.Add(catNode);
// 取得該分類產品
var products = ProductsBLL.GetProductsByCategoryID(cat.CategoryID);
foreach (var prod in products)
{
SiteMapNode prodNode = new SiteMapNode(this,
"Prod_" + prod.ProductID,
"~/ProductDetail.aspx?ProductID=" + prod.ProductID,
prod.ProductName);
catNode.ChildNodes.Add(prodNode);
}
}
return rootNode;
}
}
// 必須實作但動態 Provider 通常不支援
protected override void AddNode(SiteMapNode node, SiteMapNode parentNode) { throw new NotSupportedException(); }
protected override void RemoveNode(SiteMapNode node) { throw new NotSupportedException(); }
}
<siteMap defaultProvider="DynamicSiteMapProvider">
<providers>
<add name="DynamicSiteMapProvider"
type="Namespace.DynamicSiteMapProvider, AssemblyName"
securityTrimmingEnabled="true" />
</providers>
</siteMap>
自訂 SiteMapProvider 從 BLL 動態建構節點樹,完美解決動態內容導航需求。配合 securityTrimmingEnabled 自動過濾無權限節點。參考 Jeff Prosise 關於 SQL 儲存 SiteMap 的文章。