iT邦幫忙

2021 iThome 鐵人賽

DAY 11
0
自我挑戰組

.NET Core MVC網頁應用開發系列 第 16

.NET Core第16天_AnchorTagHelper的使用

AnchorTagHelper(錨點標籤協助程式)
為將HTML封裝後的定位標籤類別程式

AnchorTagHelper.cs

#region 組件 Microsoft.AspNetCore.Mvc.TagHelpers, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
// C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\5.0.0\ref\net5.0\Microsoft.AspNetCore.Mvc.TagHelpers.dll
#endregion

using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Collections.Generic;

namespace Microsoft.AspNetCore.Mvc.TagHelpers
{
    //
    // 摘要:
    //     Microsoft.AspNetCore.Razor.TagHelpers.ITagHelper implementation targeting <a>
    //     elements.
    [HtmlTargetElement("a", Attributes = "asp-action")]
    [HtmlTargetElement("a", Attributes = "asp-controller")]
    [HtmlTargetElement("a", Attributes = "asp-area")]
    [HtmlTargetElement("a", Attributes = "asp-page")]
    [HtmlTargetElement("a", Attributes = "asp-page-handler")]
    [HtmlTargetElement("a", Attributes = "asp-fragment")]
    [HtmlTargetElement("a", Attributes = "asp-host")]
    [HtmlTargetElement("a", Attributes = "asp-protocol")]
    [HtmlTargetElement("a", Attributes = "asp-route")]
    [HtmlTargetElement("a", Attributes = "asp-all-route-data")]
    [HtmlTargetElement("a", Attributes = "asp-route-*")]
    public class AnchorTagHelper : TagHelper
    {
        //
        // 摘要:
        //     Creates a new Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.
        //
        // 參數:
        //   generator:
        //     The Microsoft.AspNetCore.Mvc.ViewFeatures.IHtmlGenerator.
        public AnchorTagHelper(IHtmlGenerator generator);

        public override int Order { get; }
        //
        // 摘要:
        //     The name of the action method.
        //
        // 備註:
        //     Must be null if Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Route or
        //     Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Page is non-null.
        [HtmlAttributeName("asp-action")]
        public string Action { get; set; }
        //
        // 摘要:
        //     The name of the controller.
        //
        // 備註:
        //     Must be null if Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Route or
        //     Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Page is non-null.
        [HtmlAttributeName("asp-controller")]
        public string Controller { get; set; }
        //
        // 摘要:
        //     The name of the area.
        //
        // 備註:
        //     Must be null if Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Route is
        //     non-null.
        [HtmlAttributeName("asp-area")]
        public string Area { get; set; }
        //
        // 摘要:
        //     The name of the page.
        //
        // 備註:
        //     Must be null if Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Route or
        //     Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Action, Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Controller
        //     is non-null.
        [HtmlAttributeName("asp-page")]
        public string Page { get; set; }
        //
        // 摘要:
        //     The name of the page handler.
        //
        // 備註:
        //     Must be null if Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Route or
        //     Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Action, or Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Controller
        //     is non-null.
        [HtmlAttributeName("asp-page-handler")]
        public string PageHandler { get; set; }
        //
        // 摘要:
        //     The protocol for the URL, such as "http" or "https".
        [HtmlAttributeName("asp-protocol")]
        public string Protocol { get; set; }
        //
        // 摘要:
        //     The host name.
        [HtmlAttributeName("asp-host")]
        public string Host { get; set; }
        //
        // 摘要:
        //     The URL fragment name.
        [HtmlAttributeName("asp-fragment")]
        public string Fragment { get; set; }
        //
        // 摘要:
        //     Name of the route.
        //
        // 備註:
        //     Must be null if one of Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Action,
        //     Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Controller, Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Area
        //     or Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Page is non-null.
        [HtmlAttributeName("asp-route")]
        public string Route { get; set; }
        //
        // 摘要:
        //     Additional parameters for the route.
        [HtmlAttributeName("asp-all-route-data", DictionaryAttributePrefix = "asp-route-")]
        public IDictionary<string, string> RouteValues { get; set; }
        //
        // 摘要:
        //     Gets or sets the Microsoft.AspNetCore.Mvc.Rendering.ViewContext for the current
        //     request.
        [HtmlAttributeNotBound]
        [ViewContext]
        public ViewContext ViewContext { get; set; }
        //
        // 摘要:
        //     Gets the Microsoft.AspNetCore.Mvc.ViewFeatures.IHtmlGenerator used to generate
        //     the Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper's output.
        protected IHtmlGenerator Generator { get; }

        //
        // 備註:
        //     Does nothing if user provides an href attribute.
        public override void Process(TagHelperContext context, TagHelperOutput output);
    }
}

新增AnchorController.cs跟相應Index檢視

AnchorController.cs

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

namespace Net5App6.Controllers
{
    public class AnchorController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}

Index.cshtml

<div>
    <a asp-controller="Home">定位點至Home</a>
    <br>
    <a asp-controller="Student">定位點至Student</a>
</div>

新增AnchorViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Net5App6.Models
{
    public class AnchorViewModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

asp-controller :
於定位標籤上使用asp-controller屬性後可生成對應URL地址
該值最終會放置於 tag的href 屬性中
運行效果:預設只有設定Controller名稱就會自動導向對應Index的檢視

https://ithelp.ithome.com.tw/upload/images/20210916/20107452NnLoEeAnpj.png

https://ithelp.ithome.com.tw/upload/images/20210916/2010745224lGccreHH.png

https://ithelp.ithome.com.tw/upload/images/20210916/20107452srbjguHIfG.png

asp-action:可以指定對應要跳轉導向至哪個action,
指定的action method必須存在於asp-controller控制器中或目前控制器當中。
AnchorController.cs

./Views/Anchor/Index.cshtml

<div>
    <a asp-controller="Home">定位點至Home預設Index</a>
    <br>
    <a  asp-action="show">定位點至當前控制器(Anchor)的Show</a>
    <br>
    <a asp-controller="Student" asp-action="show">定位點至Student的Show</a>
</div>

所以當預設我們只有指定asp-action的時候會抓當前檢視所隸屬的Controller為誰作優先
以上面例子跑到瀏覽器執行狀況就會以Anchor控制器下的Show為優先。

https://ithelp.ithome.com.tw/upload/images/20210916/20107452GIvPh4JG99.png

asp-host : 可以指定主機名稱、域名

asp-protocol : 於 tag中可以藉由asp-host來指定URL協定要是http或https,預設沒有指定會採用80的http。

./Views/Anchor/Index.cshtml

<div>
    <a asp-controller="Student" asp-action="show" asp-host="kytest" asp-protocol="https">定位點至Student的Show</a>
</div>

https://ithelp.ithome.com.tw/upload/images/20210916/20107452tiL6DX85fv.png

asp-route : 路由模板
可以預先在特定Controller的action method上面透過
[Route("路由模板字串" , Name="別名")]來縮短在檢視中呼叫要多寫asp-controller 、 asp-acton等屬性,直接asp-route="別名"即可導向對應路由指定的action。
(PS:asp-route不可以跟 asp-controller 、asp-action 、asp-page、asp-page-handler同時並存,一次只能選擇要用asp-route或asp-controller 、asp-action...等。)

AnchorController.cs

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

namespace Net5App6.Controllers
{
    public class AnchorController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        [Route("/Student/Show", Name = "stu_show")]
        public IActionResult Show()
        {
            return View();
        }
    }
}

./Views/Anchor/Index.cshtml

<div>
    <a asp-controller="Student" asp-action="show" >定位點至Student的Show</a>
    <br>
    <a asp-route="stu_show">定位點至Student的Show(透過asp-route)</a>
</div>

https://ithelp.ithome.com.tw/upload/images/20210916/201074529d67NnTtDx.png

asp-route-{value}:URL訪問帶有參數的路由模板形式,{value}代表參數的名稱也就是URL 問號
後面的參數。

./Views/Anchor/Index.cshtml

<div>

    <a asp-controller="Anchor" asp-action="PlayerInfo" asp-route-name="戴姿穎">導向PlayerInfo</a>
    <br />
    <a asp-controller="Anchor" asp-action="ClassInfo" asp-route-class_name="一年8班" asp-route-teacher="王政忠" >導向ClassInfo</a>
</div>

AnchorController.cs

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

namespace Net5App6.Controllers
{
    public class AnchorController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        [Route("/Student/Show", Name = "stu_show")]
        public IActionResult Show(string name)
        {
            return View();
        }

        public IActionResult PlayerInfo(string name)
        {
            ViewBag.Name = name;
            return View();
        }

        public IActionResult ClassInfo(string class_name, string teacher)
        {
            ViewBag.class_name = class_name;
            ViewBag.teacher = teacher;
            return View();
        }
    }
}

運行效果
https://ithelp.ithome.com.tw/upload/images/20210916/20107452fMidwSK0kK.png

藉此可觀察當要傳遞多個參數則要多自訂**asp-route-{value}**多一些,而在實務上可能也會感覺太冗長。

asp-all-route-data : 是針對多參數的一個key-value集合容器來一次大量參數設置,因此就不需要再tag自動太多屬性。

比方像上面要傳送班級跟導師名兩個參數就可以改寫
./Views/Anchor/Index.cshtml

@{
    var url_params = new Dictionary<string, string>()
{
        {"class_name","一年8班" },
        {"teacher","王政忠" }
    };
}

<div>

    <a asp-controller="Anchor" asp-action="ClassInfo" asp-route-class_name="一年8班" asp-route-teacher="王政忠">導向ClassInfo</a>
    <br />
    <a asp-controller="Anchor" asp-action="ClassInfo" asp-all-route-data="url_params">導向ClassInfo(asp-all-route-data)</a>
</div>

https://ithelp.ithome.com.tw/upload/images/20210916/20107452pix944SBq8.png

asp-fragment : 有想要追加到URL片段的部分可以透過此屬性設置,增加#後頭的部分。
(於同一個頁面在做定位的部分)
https://ithelp.ithome.com.tw/upload/images/20210916/20107452cMpXf7vjxQ.png

AnchorTagHelper 跟 ViewModel搭配使用

./Views/Anchor/Index.cshtml

@model AnchorViewModel

<div>
    <a asp-route-id="@Model.Id" >@Model.Name</a>
</div>

AnchorController.cs

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

namespace Net5App6.Controllers
{
    public class AnchorController : Controller
    {
        public IActionResult Index()
        {
            var anchor_model = new AnchorViewModel()
            {
                Id = 1,
                Name = "Kevin"
            };
            return View(anchor_model);
        }
    }
}

https://ithelp.ithome.com.tw/upload/images/20210916/20107452k0Otg8lLFQ.png

本篇已同步發表至個人部落格
https://coolmandiary.blogspot.com/2021/08/net-core16anchortaghelper.html


上一篇
.NET Core第15天_MVC的TagHeper使用_微軟Web應用框架中前端部分的演進
下一篇
.NET Core第17天_LabelTagHelper的使用
系列文
.NET Core MVC網頁應用開發30

尚未有邦友留言

立即登入留言