如果你在使用ASP.NET網站,同時又希望它Search Engine Friendly一些,很可能你就希望它有一個Sitemaps。在這裡我們說的不是ASP.NET的SiteMap,而是Sitemaps.org定義的基於XML的Sitemaps協議,注意這兩個名字的大小寫以及單複數,之後我都會這樣區分它們。Sitemaps協議有點類似RSS或者Atom,只不過它描述的不是最近的內容更新,而是整個網站的地圖,主要用來描述特定URL的重要程度、更新時間及頻率等。搜尋引擎如Google是支援Sitemaps的,通過Google Webmaster Tools(以前叫做Google Sitemaps)你可以提交你的網站的Sitemaps,以便Google更好地索引你的網站。
簡單調用
在ASP.NET Futures (May CTP)之前,如果你想要為你的ASP.NET網站增加Sitemaps支援,恐怕必須自己實現一個特殊的頁面(或者HttpHandler)用於讀取ASP.NET SiteMap並輸出為Sitemaps協議。而現在這工作可以交給ASP.NET Futures的AspNetSiteMapSearchSiteMapProvider來做了,你需要做的僅僅是在web.config中寫上幾句。由於這個功能屬於ASP.NET Futures中SearchSiteMap這個類別,所以需要在web.config中對該節進行配置:
以下為引用的內容:
<microsoft.web.preview> <searchSiteMap enabled="true"> <providers> <add name="Navigation" type="Microsoft.Web.Preview.Search.AspNetSiteMapSearchSiteMapProvider, Microsoft.Web.Preview"/> </providers> </searchSiteMap> </microsoft.web.preview> |
在這個配置裡面,我們啟用了SearchSiteMap,然後配置了一個名為"Navigation"的Provider,此Provider使用AspNetSiteMapSearchSiteMapProvider類,就這麼簡單,和配置任何其他Provider的形式完全一致。之後你還需要確保一下有關的HttpHandler配置好了,如果你建立網站時使用的模板是ASP.NET Futures的,那麼HttpHandler就應該配置好的了,配置資訊如下:
以下為引用的內容:
<add verb="*" path="SearchSiteMaps.axd" type="Microsoft.Web.Preview.Search.SearchSiteMapHandler" validate="True"/> |
這時候,如果你的網站已經正常啟用ASP.NET自身的SiteMap功能,例如使用靜態Web.sitemap,那麼訪問SearchSiteMap.axd就應該能看到按照Sitemaps協議輸出的結果。這時候或許你會很奇怪,為什麼結果只有一條記錄呢?這就是Sitemaps的遞迴調用了,這個主Sitemaps僅僅聲名了我們之前配置的那個名為"Navigation"的Sitemaps的地址,也就是SearchSiteMaps.axd?sitemap=Navigation。開啟這個地址,你會發現仍然是一個Sitemaps,它裡麵包含的就是ASP.NET SiteMap提供的資料了。
深入看看
接下來,我們用Reflector來看看Microsoft.Web.Preview.Search下面的一些類的實現方式。我不準備詳細分析代碼了,因為代碼都很簡單,直接說說看完的結果吧。如果你之前瀏覽根據SiteMap產生的Sitemaps時發現少了些東西,在這裡你就知道如何把這些項目補充上去了。Sitemaps協議中關於一個URL能夠包括以下幾樣資訊:
地址:也就是URL本身
最後更新時間
更新頻率:此URL的內容多久更新一次
重要程度:一個0到1的值,預設值為0.5,搜尋引擎並不一定根據這個值來判斷URL的真正重要程度
然而自動產生的Sitemaps僅僅包括前兩項資訊,如果我們需要後兩項資訊就需要手動增加。怎樣手動增加呢?因為SiteMapNode類似於字典,能夠訪問this [string key],所以只要SiteMapNode[]存在"lastModified"/"changeFrequency"/"priority"這幾個值就能自動輸出到Sitemaps中,而且"lastModified"會覆蓋對應Page的aspx檔案的真實最後更新時間。
簡單舉例說明這功能怎麼用,假設你使用的是靜態Web.sitemap,我們已經習慣這樣定義一個SiteMapNode:
以下為引用的內容:
<siteMapNode url="Default.aspx" title="Welcome" description="" /> |
而增加特定的屬性只需要這樣定義:
以下為引用的內容:
<siteMapNode url="Default.aspx" title="Welcome" description="" changeFrequency="daily" priority="0.8" /> |
支援Dynamic Data
上面說了那麼多,也就僅僅能做到支援系統內建的SiteMap,而實際上SearchSiteMap還能夠對Dynamic Data提供特殊的支援。Dynamic Data簡單易用,好像Ruby on Rails那樣支援scaffolding,預覽了ASP.NET將來在敏捷方面的發展。有關Dynamic Data Control的詳細資料,請參考Dflying的文章,我們這裡僅討論SearchSiteMap的支援:
ASP.NET Futures初探——動態資料控制項(Dynamic Data Control):入門
ASP.NET Futures初探——動態資料控制項(Dynamic Data Control):深入一些
需要支援Dynamic Data的話,首先你要實現自己的DynamicDataSearchSiteMapProvider。大家不要一看到要繼承自系統類別實現自己的類就覺得是非常複雜的事情,其實這裡我們僅需要override掉一個函數,也就是DynamicDataSearchSiteMapProvider.DataQuery()。在這個函數中,我們需要返回一個IEnumerable,其中的元素需要具有主鍵列名屬性以及以下屬性:
以下為引用的內容: SiteMapLastModified SiteMapChangeFrequency SiteMapPriority |
你很可能會問,為什麼要是不確定類型的IEnumerable而不是確定類型的List<>呢?想想.NET Framework的什麼部分用IEnumerable用得最多吧,那就是LINQ。如果你在QueryData()中直接使用LINQ來篩選資料,你就不需要建立自訂類型並且自己填充IEnumerable了。況且,主鍵列名也不是確定的,如果用一個屬性記錄其名稱用另外一個屬性記錄其值那就很麻煩了,所以ASP.NET Futures選擇了上述充分發揮LINQ優勢的做法。
最後,我個人感覺SearchSiteMapProviderBase的設計有點問題,它作為AspNetSiteMapSearchSiteMapProvider與DynamicDataSearchSiteMapProvider的基類,其中包括QueryData()方法,然而此方法只有DynamicDataSearchSiteMapProvider用到,很顯然就應該將它放置到DynamicDataSearchSiteMapProvider裡面。