使用ASP.NET Core MVC Filter產生Meta標籤

by vivid 6. 九月 2017 15:10

.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號:
N170918701
出刊日期: 2017/9/6

為了要讓個人或公司的網站能夠支援搜尋引擎最佳化,以及讓網頁分享到社群網站,如Facebook、Google+時,能夠正確的顯示網站的標題、作者以及圖片…等等資訊,我們會在網頁中加上許多<meta>標籤,或者是一些結構化資料。

例如以下網頁加入了許多Meta標籤:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="author" content="Candy">
  <meta name="copyright" content="Candy">

  <meta name="og:title" content="優看,YouCome" />
  <meta name="og:type" content="website" />
  <meta name="og:url" content="https://www.123.com.tw/" />
  <meta name="og:image" content="https://www.123.com.tw/main.jpg" />
  <meta name="og:description" content="IT 訓練中心" />

  <meta itemprop="name" content="優看,YouCome" />
  <meta itemprop="image" content="https://www.123.com.tw/main.jpg" />
  <meta itemprop="description" content="IT 訓練中心" />
  <title>Index</title>
</head>
<body>
  <h1>Home</h1>
</body>
</html>


其中這行用來設定網頁編碼為「UTF-8萬國碼」:

<meta charset="utf-8" />

其中這行是給行動裝置看的,設定可視區域等同於行動裝置寬度,縮放比例是一比一:

<meta name="viewport" content="width=device-width, initial-scale=1.0">

其中這行用來設定網頁的作者名稱:

<meta name="author" content="Candy">

其中這行用來設定網頁的版權或著作權聲明:

<meta name="copyright" content="Candy">

以下這幾行是給Facebook看的,當你將網頁分享到臉書時,才會正確顯示網站的資訊,更多關於Open Graph protocol的說明請參考http://ogp.me/網站:

<meta name="og:title" content="優看,YouCome" />
<meta name="og:type" content="website" />
<meta name="og:url" content="https://www.123.com.tw/" />
<meta name="og:image" content="https://www.123.com.tw/main.jpg" />
<meta name="og:description" content="IT 訓練中心" />

而以下這幾行則是給Google+看的,更多關於結構化資料可參閱:http://schema.org網站的說明:

<meta itemprop="name" content="優看,YouCome" />
<meta itemprop="image" content="https://www.123.com.tw/main.jpg" />
<meta itemprop="description" content="IT 訓練中心" />

若這些<meta>標籤資料不是寫死的,有時可能是放在設定檔,或資料庫之中,那麼透過程式自動產生就會讓事情變得簡單許多。這一篇文章將介紹設計ASP.NET Core MVC網站應用程式時,利用Filter(篩選)來自動產生這些標籤。

篩選(Filter)

篩選(Filter)可以在請求處理管線(request processing pipeline)中特定階段之前與之後執行程式碼。請參考下圖所示,ASP.NET MVC Core MVC內建許多Filter,如authorization,在請求處理管線的一開始執行,之後不做動作,防止存取未授權的資源;Resource filter在authorization filter之後執行,可以用來實作提升效能的程式。這張圖並沒有畫出所有內建的Filter,詳細的說明可以查詢官方的文件。

clip_image002

圖 1:ASP.NET MVC Core MVC請求處理管線(request processing pipeline)。

Filter支援同步與非同步,需分別實作不同的介面:IActionFilter 與IAsyncActionFilter。同步的Filter可以實作OnActionExecuting方法在Action之前執行程式碼,或實作OnActionExecuted方法,在Action方法回傳後執行。注意,實作同步或非同步都好,但不要同時實作。呼叫時非同步Filter優先於同步Filter。如果同步與非同步介面都有實作,則只會叫用非同步的程式碼。以下的範例將設計成同步Filter。

 

建立ASP.NET Core Web Application專案

啟動Visual Studio 2017開發環境。從「File」-「New」-「Project」,在「New Project」對話盒中,確認視窗上方.NET Framework的目標版本為「.NET Framework 4.6」或以上版本,選取左方「Installed」-「Templates」-「Visual C#」程式語言,從「.NET Core」分類中,選取「ASP.NET Core Web Application (.NET Core)」。設定專案名稱與專案存放路徑,按下「OK」鍵,請參考下圖所示:

clip_image004

圖 2:建立ASP.NET Core Web Application專案。

在「New ASP.NET Core Web Application (.NET Core) 」對話盒中,確認上方的ASP.NET Core版本為「ASP.NET Core 1.1」,選取下方的「Web Application」樣版,清除勾選下方的「Enable Docker Support」核取方塊,確定右方的「Authentication」項目設定為「No Authentication」,然後按下「OK」按鈕建立專案,請參考下圖所示:

clip_image006

圖 3:建立範本專案。

設計Filter類別

從Visual Studio 2017開發工具 -「Solution Explorer」視窗 - 專案名稱上方按滑鼠右鍵,從快捷選單選擇「Add」- 「New Folder」,選項,目前畫面看起來如下,將新建立的資料夾命名為「Filters」,請參考下圖所示:

clip_image008

圖 4:建立Filters資料夾。

定義MetaTagFilter類別。從Visual Studio 2017開發工具 -「Solution Explorer」視窗- 專案的「Filters」資料夾上方按滑鼠右鍵,從快捷選單選擇「Add」- 「New Item」項目,開啟「Add New Item」對話盒,從右上方文字方塊輸入「Class」搜尋,選取Class,設定名稱為「MetaTagFilter」,然後按下「Add」按鈕,建立新類別,請參考下圖所示:

clip_image010

圖 5:新增MetaTagFilter類別。

在MetaTagFilter.cs檔案加入以下程式碼,MetaTagFilter類別包含兩個建構函式,在沒有參數的建構函式之中設定Meta相關資料的預設值。MetaTagFilter類別實作了IActionFilter介面,在OnActionExecuting方法將Meta標籤所需的資料放到控制器的ViewBag之中:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;
namespace MyFilterDemo.Filters {
  public class MetaTagFilter : IActionFilter {
    private string author { get; set; }
    private string copyright { get; set; }
    private string title { get; set; }
    private string type { get; set; }
    private string url { get; set; }
    private string description { get; set; }
    private string image { get; set; }
    public MetaTagFilter( ) : this(
      author: "Mary" ,
      copyright: "Mary" ,
      title: "優看,YouCome" ,
      type: "website" ,
      url: "https://www.test.com.tw/" ,
      description: "IT教育訓練中心" ,
      image: "https://www.test.com.tw/main.jpg" ) {
    }

    public MetaTagFilter( string author , string copyright , string title , string type , string url , string description , string image ) {
      this.author = author;
      this.copyright = copyright;
      this.title = title;
      this.type = type;
      this.url = url;
      this.description = description;
      this.image = image;
    }
    public void OnActionExecuted( ActionExecutedContext context ) {
    }
    public void OnActionExecuting( ActionExecutingContext context ) {
      dynamic controller = context.Controller;
      controller.ViewBag.Author = this.author;
      controller.ViewBag.Copyright = this.copyright;
      controller.ViewBag.Title = this.title;
      controller.ViewBag.Type = this.type;
      controller.ViewBag.Url = this.url;
      controller.ViewBag.Description = this.description;
      controller.ViewBag.image = this.image;
    }
  }

}

 

修改專案根目錄下的Startup.cs檔案,在Startup類別的ConfigureServices方法中services.AddMvc方法內加入以下程式碼,建立MetaTagFilter物件,並將之加到全域Filters:

public void ConfigureServices( IServiceCollection services ) {
  services.AddMvc( options => {
    options.Filters.Add( new Filters.MetaTagFilter( ) );
  } );
}

設計部分檢視(Partial View)

本範例要將Meta標籤放在一個部分檢視(Partial View)之中,然後利用ViewBag取得控制器傳遞過來的資料,來建立完整的Meta標籤。先從「Solution Explorer」視窗,「Views」-「Shared」資料夾上方按滑鼠右鍵,從快捷選單選擇「Add」- 「New Item」項目,開啟「Add New Item」對話盒,在「Add New Item」對話盒右上方文字方塊輸入「View」搜尋,選取「MVC View Page」,設定名稱為「_MetaTag」,然後按下「Add」按鈕,請參考下圖所示:

clip_image012

圖 6:加入部分檢視。

在_MetaTag.cshtml檔案中加入以下程式碼,因為ASP.NET MVC Core預設會將文字編碼,所以中文字無法正確顯示出來,範例中Title與Description有使用到中文字,所以叫用HTML.Raw方法,讓中文字不要被編碼處理:

@*General*@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="author" content="@ViewBag.Author">
<meta name="copyright" content="@ViewBag.Copyright">


@*Facebook*@
<meta name="og:title" content="@Html.Raw(ViewBag.Title)" />
<meta name="og:type" content="@ViewBag.Type" />
<meta name="og:url" content="@ViewBag.Url" />
<meta name="og:image" content="@ViewBag.Image" />
<meta name="og:description" content="@Html.Raw(ViewBag.Description)" />

@*google + *@
<meta itemprop="name" content="@ViewBag.Title" />
<meta itemprop="image" content="@ViewBag.Image" />
<meta itemprop="description" content="@Html.Raw(ViewBag.Description)" />

修改專案中Views\Shared資料夾下的_Layout.cshtml檔案,這個檔案定義了範本網站中所有網頁共用的HTML項目。我們在<head>標籤中叫用Html.Partial方法插入「_MetaTag」部分檢視的內容:

<head>
  @Html.Partial( "_MetaTag" )
  <environment names="Development">
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />
  </environment>
  <environment names="Staging,Production">
    <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
          asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
          asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
    <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
  </environment>
  @Html.Raw( JavaScriptSnippet.FullScript )
</head>

現在程式大致完成了,選取Visual Studio 「Build」-「Build Solution」編譯目前的專案,確認程式碼能正確編譯。按CTRL+F5執行網站首頁,執行結果參考如下,在網頁空白處按滑鼠右鍵,然後選取快捷選單中的「View page source」項目,看看產生出來的Meat標籤:

clip_image014

圖 7:檢視首頁執行結果。

Index檢視執行完產生出的結果,請參考下圖所示:

clip_image016

圖 8:Index檢視執行結果。

Contact檢視執行後的網頁原始程式碼,請參考下圖所示:

clip_image018

圖 9:Contact檢視執行結果。

結束執行程式,回到Visual Studio 開發工具程式編輯畫面。

使用Attribute套用

上例的Filter是在Startup類別Configure方法建立一個MetaTagFilter物件來服務Meta標籤所需資料。不過若某些網頁需要的參數不同,那麼我們可以將之設計成Attribute來套用,如此就可以自訂參數。回到Visual Studio設計畫面,修改MetaTagFilter.cs,定義MetaTagAttribute類別,並將原來的MetaTagFilter定義在MetaTagAttribute類別之中。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;

namespace MyFilterDemo.Filters {

  public class MetaTagAttribute : TypeFilterAttribute {
    public MetaTagAttribute( ) : base( typeof( MetaTagFilter ) ) {

    }
    public class MetaTagFilter : IActionFilter {
      private string author { get; set; }
      private string copyright { get; set; }
      private string title { get; set; }
      private string type { get; set; }
      private string url { get; set; }
      private string description { get; set; }
      private string image { get; set; }
      public MetaTagFilter( ) : this(
        author: "Mary" ,
        copyright: "Mary" ,
        title: "優看,YouCome" ,
        type: "website" ,
        url: "https://www.test.com.tw/" ,
        description: "IT教育訓練中心" ,
        image: "https://www.test.com.tw/main.jpg" ) {
      }

      public MetaTagFilter( string author , string copyright , string title , string type , string url , string description , string image ) {
        this.author = author;
        this.copyright = copyright;
        this.title = title;
        this.type = type;
        this.url = url;
        this.description = description;
        this.image = image;
      }
      public void OnActionExecuted( ActionExecutedContext context ) {
      }
      public void OnActionExecuting( ActionExecutingContext context ) {
        dynamic controller = context.Controller;
        controller.ViewBag.Author = this.author;
        controller.ViewBag.Copyright = this.copyright;
        controller.ViewBag.Title = this.title;
        controller.ViewBag.Type = this.type;
        controller.ViewBag.Url = this.url;
        controller.ViewBag.Description = this.description;
        controller.ViewBag.image = this.image;
      }
    }
  }
}

 

修改Startup類別,在ConfigureServices方法加入以下程式碼:

public void ConfigureServices( IServiceCollection services ) {
  services.AddMvc( );
}

修改HomeController類別程式碼,分別在HomeController類別與Contact方法上方套用MetaTag Attribute,並設定成不同的參數:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using MyFilterDemo.Filters;

namespace MyFilterDemo.Controllers {
  [MetaTag( Arguments = new object[] {"Candy" ,"Candy" , "優看,YouCome" , "website" ,
  "https://www.123.com.tw/" ,
   "IT 訓練中心" ,
   "https://www.123.com.tw/main.jpg" } )]
  public class HomeController : Controller {
    public IActionResult Index( ) {
      return View( );
    }

    public IActionResult About( ) {
      ViewData["Message"] = "Your application description page.";

      return View( );
    }
    [MetaTag( Arguments = new object[] {"Jo" ,"Jo" , "優西,YouSee" , "website" ,
  "https://www.456.com.tw/" ,
   "Best訓練中心" ,
   "https://www.456.com.tw/main.jpg" } )]
    public IActionResult Contact( ) {
      ViewData["Message"] = "Your contact page.";

      return View( );
    }

    public IActionResult Error( ) {
      return View( );
    }
  }
}

 

 

選取Visual Studio 「Build」-「Build Solution」編譯目前的專案,確認程式碼能正確編譯。然後按CTRL+F5執行網站首頁,執行結果參考如下,首頁Index檢視執行後產生的Meta標籤,請參考下圖所示:

clip_image020

圖 10:Index檢視執行結果。

而Contact檢視執行完的Meta標籤長像如下圖所示:

clip_image022

圖 11:Contact檢視執行結果。

Tags:

.NET Magazine國際中文電子雜誌 | 許薰尹Vivid Hsu | ASP.NET Core MVC

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List