ASP.NET MVC快速產生SiteMap的擴充程式 - MvcSiteMapProvider

WebForm有,MVC有沒有

在 WebForm 拜控制項所賜,讓我們可以快速且容易去設置與產出網頁的 SiteMap(中文稱巡覽列、導覽列),不過在 ASP.NET MVC 之下一開始並無控制項觀念,也經常碰到有 WebForm 經驗正在學習 ASP.NET MVC 的新手常問說:WebForm 有什麼控制項的功能,ASP.NET MVC 有沒有。SiteMap 就是常被問到的一項。

說實話,剛接觸 ASP.NET MVC 2 時是比較辛苦,因為沒提供的功能都必須自己手工刻。隨著時間的經過,後來有了 NuGet 的加持直到現在 ASP.NET MVC 4,整個 ASP.NET MVC 上的擴充套件(擴充程式)已經非常完整,今天要介紹的 MvcSiteMapProvider 都一套快速提供 MVC 專案使用的 Sitemap 擴充套件。

安裝與設置MvcSiteMapProvider擴充套件

首先我們先開一個測試用的 MVC - 網際網路專案,然後開啟【套件管理器主控台】:

PM> Install-Package MvcSiteMapProvider

安裝之後,會開啟一個 Mvc.sitemap 的檔案,如果讀者看過 Webform 的 SiteMap 設置檔會有相似的感覺。

   <?xml version="1.0" encoding="utf-8" ?>
   <mvcSiteMap xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-3.0"
               xsi:schemaLocation="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-3.0 MvcSiteMapSchema.xsd"
               enableLocalization="true">

     <mvcSiteMapNode title="Home" controller="Home" action="Index">
       <mvcSiteMapNode title="About" controller="Home" action="About"/>
       <mvcSiteMapNode title="Contact" controller="Home" action="Contact"/>
     </mvcSiteMapNode>

   </mvcSiteMap>
  

<mvcSiteMapNode> 是最主要設定段落,內容很簡單,就是設定 controller 與 action,依各位專案的需求去設計出自己的層次架構即可。例如,我們依 MVC - 網際網路專案去調整為 Home 的 Index 為主節點(程式裡稱 node),Home 的 About 與 Contact 為子節點。這樣我們就完成 MvcSiteMapProvider 的設置。

設置 SiteMap 出現位置

接下來我們必須設置 SiteMap 的出現位置,一般會設置在兩個位置:

  1. _Layout.cshtml 或 _Layout.vbhtml
    進行全網站的設置。
  2. Views
    進行各別頁面的設置。

開啟範例專案的 _Layout.vbhtml 並修改 <div id=body> 的內容:

   <div id="body">
       @Html.MvcSiteMap().Menu(False, False, True)
       目前位置:@Html.MvcSiteMap().SiteMapPath()
       @RenderSection("featured", required:=false)
       <section class="content-wrapper main-content clear-fix">
           @RenderBody()
       </section>
   </div>
  

@Html.MvcSiteMap().Menu(False, False, True) 會產生整個網站的連結清單。@Html.MvcSiteMap().SiteMapPath() 會產生麵包屑巡覽(breadcrumbs)。

MvcSiteMapProvider產生的Sitemap

由產生的 HTML 程式碼來看比較清楚:

   <ul id="menu">
       <li>
       <a href="/">Home</a>
     <ul>
         <li>
         <a href="/Home/About">About</a>
         </li>
         <li>
         <a href="/Home/Contact">Contact</a>
         </li>
     </ul>
       </li>
   </ul>
   目前位置:<a href="/">Home</a> > About
  

其他程式碼細部控制請參考MvcSiteMapProvider官方文件

客製化 MvcSiteMapProvider 範本

如果各位想要客製化 MvcSiteMapProvider 的輸出結果,例如麵包屑巡覽(breadcrumbs)預設是使用 > 符號,但你想改為使用 | 符號或 - 符號,又或者想要修改 <ul id="menu"> 裡的 id 設置,可以到 ~/Shared/DisplayTemplates 之下進行修改,*.ascx 是給 ASPX 引擎使用,*.cshtml 是給 Razor 引擎使用,可依專案類型保留其中一種即可。以修改麵包屑巡覽符號而言,你必須修改 SiteMapTitleHelperModel.cshtml 這支檔案內容。

MvcSiteMapProvider for vbhtml 範本

MvcSiteMapProvider 沒有提供 *.vbhtml,雖然在MVC - VB專案內使用 *.cshtml 不會有任何問題,不過我還是順手給他轉換了一下,以保持專案內容的一致性。

MenuHelperModel.vbhtml

   @Modeltype MvcSiteMapProvider.Web.Html.Models.MenuHelperModel
   @Imports System.Web.Mvc.Html
   @Imports MvcSiteMapProvider.Web.Html.Models

   <ul id="menu">
       @For Each node In Model.Nodes
           @<li>
               @Html.DisplayFor(Function(m) node)
               @If node.Children.Any() Then
                   Html.DisplayFor(Function(m) node.Children)
               End If
            </li>
       Next
   </ul>   
  

SiteMapHelperModel.vbhtml

  @ModelType MvcSiteMapProvider.Web.Html.Models.SiteMapHelperModel
  @Imports System.Web.Mvc.Html
  @Imports MvcSiteMapProvider.Web.Html.Models

  <ul class="sitemap">
      @For Each node In Model.Nodes
          @<li>
              @Html.DisplayFor(Function(m) node)
              @If node.Children.Any() Then
                  Html.DisplayFor(Function(m) node.Children)
              End If
           </li>
      Next
  </ul>
  

SiteMapNodeModel.vbhtml

  @ModelType MvcSiteMapProvider.Web.Html.Models.SiteMapNodeModel
  @Imports System.Web.Mvc.Html
  @Imports MvcSiteMapProvider.Web.Html.Models

  @If Model.IsCurrentNode AndAlso Model.SourceMetadata("HtmlHelper").ToString() <> "MvcSiteMapProvider.Web.Html.MenuHelper" Then
      @<text>@Model.Title</text>
  ElseIf Model.IsClickable Then
      @<a href="@Model.Url">@Model.Title</a>
  Else
      @<text>@Model.Title</text>    
  End If
  

SiteMapNodeModelList.vbhtml

  @ModelType MvcSiteMapProvider.Web.Html.Models.SiteMapNodeModelList
  @Imports System.Web.Mvc.Html
  @Imports MvcSiteMapProvider.Web.Html.Models

  <ul>
      @For Each node In Model
      @<li>
          @Html.DisplayFor(Function(m) node)
          @If node.Children.Any() Then
              @Html.DisplayFor(Function(m) node.Children)
          End If
      </li>
      Next
  </ul>
  

SiteMapPathHelperModel.vbhtml

  @ModelType MvcSiteMapProvider.Web.Html.Models.SiteMapPathHelperModel
  @Imports System.Web.Mvc.Html
  @Imports System.Linq
  @Imports MvcSiteMapProvider.Web.Html.Models

  @For Each node In Model
      @Html.DisplayFor(Function(m) node)

      @If node IsNot Model.Last() Then
              @<text> > </text>
      End If
  Next
  

SiteMapTitleHelperModel.vbhtml

  @ModelType MvcSiteMapProvider.Web.Html.Models.SiteMapTitleHelperModel
  @Imports System.Web.Mvc.Html
  @Imports MvcSiteMapProvider.Web.Html.Models

  @Model.CurrentNode.Title
  

1 則留言:

  1. 您好:
    感謝您的教學,想請教這個方法可以提交給google SEO 讓搜尋去做優化嗎?
    如果可以詳細應該怎麼做呢?

    回覆刪除

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。