GVKun编程网logo

asp.net-core – TagHelper,用于将路由值作为链接的一部分传递(asp.net mvc路由机制)

6

如果您对asp.net-core–TagHelper,用于将路由值作为链接的一部分传递感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于asp.net-core–TagHelp

如果您对asp.net-core – TagHelper,用于将路由值作为链接的一部分传递感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于asp.net-core – TagHelper,用于将路由值作为链接的一部分传递的详细内容,我们还将为您解答asp.net mvc路由机制的相关问题,并且为您提供关于.Net Core 3.1 TagHelper的使用、.NET Core MVC下的TagHelper、asp.net core 2.1 TagHelpers、ASP.NET Core 3.0 : 二十五. TagHelper的有价值信息。

本文目录一览:

asp.net-core – TagHelper,用于将路由值作为链接的一部分传递(asp.net mvc路由机制)

asp.net-core – TagHelper,用于将路由值作为链接的一部分传递(asp.net mvc路由机制)

在链接上指定asp-controller和asp-action时,还传递id属性的语法是什么?

例如。如果我想链接到给定对象的编辑URL,则所需的URL将是/ user / edit / 5。

有没有办法使用TagHelpers来实现这一点,还是还要回到@ Html.ActionLink()?

解决方法

您可以使用属性前缀asp-route-在您的路由变量名称前面。

示例:< a asp-action =“编辑”asp-route-id =“10”asp-route-foo =“bar”>编辑< / a>

.Net Core 3.1 TagHelper的使用

.Net Core 3.1 TagHelper的使用

.Net Core 3.1 TagHelper的使用,网上查了不少文章,发现有一点说的不清楚,导致自定义的TagHelper不起作用,最终原因是@addTagHelper使用有误。
一、环境
Win10、VS2019、.Net Core 3.1
二、TagHelper定义
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace PlantManagement.TagHelpers
{

[HtmlTargetElement("clauseitem")]
public class ClauseItemTagHelper: TagHelper
{
    public string RID { get; set; }
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "div";
        output.TagMode = TagMode.StartTagAndEndTag;
        output.Content.SetContent("dfdf"+RID);
    }
}

}
三、TagHelper标签使用
<clauseitem rid="1"></clauseitem>
四、ViewImports设置
@using PlantManagement
@using Kendo.Mvc.UI
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Kendo.Mvc
@addTagHelper *, PlantManagement
五、关键
@addTagHelper *, PlantManagement,不是PlantManagement.TagHelpers!

.NET Core MVC下的TagHelper

.NET Core MVC下的TagHelper

https://www.cnblogs.com/psycheeeeeblog/archive/2020/02/22/12346338.html


.NET web开发者在开发过程中,一定都踩过的坑,明明修改了js文件,可是部署到生产环境,客户反馈说:“还是报错啊”。。然后一脸懵逼的去服务器上看文件,确实已经更新了。有经验的coder可能就想到了,肯定是客户端浏览器缓存搞的鬼。

此时会告诉客户,请Crtl+F5刷新一下,这时,客户会说:“Ctrl是什么”。。

我们通常的处理办法是在js文件的引用上,手动更改版本号比如 jquery.js?v=20200222来解决。但是如果忘记改了,就麻烦了。

微软在.NET core中的Razor页面下添加了TagHelper(一些html控件的高级属性),只需要在原有引用中添加一些属性即可解决。如下图:在Script控件中添加asp-append-version属性并设置为 true 即可。

 

 

 运行之后,此时F12会在浏览器中看到如下:

 

 服务器会自动给静态资源后加上后缀来解决客户端缓存问题。贴心~

微软在很多控件上都添加了 tagHelper高级属性来解决之前版本的各式各样小问题,一起来发现吧~

asp.net core 2.1 TagHelpers

asp.net core 2.1 TagHelpers

简介

Tag Helpers 提供了在视图中更改和增强现有HTML元素的功能。将它们添加到视图中,会经过Razor模板引擎处理并创建一个HTML,之后再返回给浏览器。有一些Tag Helpers,其实作为元素或实际的标签(如environment,cache等)。

它们使用HTML方式编写,同时利用了Razor的强大功能、C#的简洁和HTML的友好性。由于使用Tag Helpers感觉如此自然,看起来像标准的HTML,前端开发人员也可以轻松地适应,不需要学习C#语法;此外,它们可以在现有元素范围内获得完美的智能提示支持。

看一下简单的例子,注意上下两行代码的区别:

<img src="~/images/banner1.svg" />
<img src="~/images/banner1.svg" asp-append-version="true"  />

它们可能会使您想到Razor中的HTML Helpers,的确,它们也具有部分相同的功能,但是,Tag Helpers使用起来更加自然;我们通常会使用它们来扩展现有HTML元素,使用HTML Helpers是用来创建一个新的HTML元素。

内置Tag Helpers列表

表单相关Tag Helpers:

Form FormAction Input Label Option Select TextArea ValidationMessage ValidationSummary

缓存:

Cache Distributed

其他:

Image Anchor Script Link Environment

**注意:**所有内置的Tag Helpers以 asp- 作为前缀。

其他标记详解

<!--<img src="/images/banner1.svg?v=GaE_EmkeBf-yBbrJ26lpkGd4jkOSh1eVKJaNOw9I4uk">-->
<img src="~/images/banner1.svg" asp-append-version="true"  />

<!--<a href="/Home/About">home/index</a>-->
<a asp-controller="Home" asp-action="About">home/About</a>


<!--asp-src-include、asp-src-exclude-->
<!--
<script src="/lib/jquery/dist/jquery.js"></script>
<script src="/lib/jquery/dist/jquery.min.js"></script>
<script src="/lib/jquery/dist/test/aa.js"></script>     ----排除
<script src="/lib/jquery/dist/test/aa.min.js"></script> ----排除
<script src="/lib/jquery/dist/test2/bb.js"></script>
-->
<script asp-src-include="~/lib/jquery/dist/**/**.js" asp-src-exclude="~/lib/jquery/dist/test/**.js"></script>


<!--
 这里src不可用。
<script src="https://cdn.bootcss.com/jquery1/3.3.1/jquery.js"></script>
<script>(window.jQuery && window.jQuery.fn||document.write("\u003Cscript src=\u0022\/lib\/jquery\/dist\/jquery.js\u0022\u003E\u003C\/script\u003E"));</script>
<script src="/lib/jquery/dist/jquery.js"></script>
-->
<script src="https://cdn.bootcss.com/jquery1/3.3.1/jquery.js"
        asp-fallback-src="~/lib/jquery/dist/jquery.js"
        asp-fallback-test="window.jQuery && window.jQuery.fn"></script>


<br/>

<!--
environment:
names 采用单个宿主环境名称或以逗号分隔的宿主环境名称列表,用于触发已包含内容的呈现。
-->
<environment names="Staging,Development">
    <strong>HostingEnvironment.EnvironmentName is Staging or Production</strong>
</environment>

<environment include="Development">
    this will run in Development <br />
</environment>

<environment include="Production">
    this will run in Production <br />
</environment>

生成

<!--<img src="/images/banner1.svg?v=GaE_EmkeBf-yBbrJ26lpkGd4jkOSh1eVKJaNOw9I4uk">-->
<img src="/images/banner1.svg?v=GaE_EmkeBf-yBbrJ26lpkGd4jkOSh1eVKJaNOw9I4uk">

<!--<a href="/Home/About">home/index</a>-->
<a href="/Home/About">home/About</a>


<!--asp-src-include、asp-src-exclude-->
<!--
<script src="/lib/jquery/dist/jquery.js"></script>
<script src="/lib/jquery/dist/jquery.min.js"></script>
<script src="/lib/jquery/dist/test/aa.js"></script>     ----排除
<script src="/lib/jquery/dist/test/aa.min.js"></script> ----排除
<script src="/lib/jquery/dist/test2/bb.js"></script>
-->
<script src="/lib/jquery/dist/jquery.js"></script>
<script src="/lib/jquery/dist/jquery.min.js"></script>
<script src="/lib/jquery/dist/test2/bb.js"></script>


<!--
 这里src不可用。
<script src="https://cdn.bootcss.com/jquery1/3.3.1/jquery.js"></script>
<script>(window.jQuery && window.jQuery.fn||document.write("\u003Cscript src=\u0022\/lib\/jquery\/dist\/jquery.js\u0022\u003E\u003C\/script\u003E"));</script>
<script src="/lib/jquery/dist/jquery.js"></script>
-->
<script src="https://cdn.bootcss.com/jquery1/3.3.1/jquery.js"></script>
<script>(window.jQuery && window.jQuery.fn||document.write("\u003Cscript src=\u0022\/lib\/jquery\/dist\/jquery.js\u0022\u003E\u003C\/script\u003E"));</script>


<br>

<!--
environment:
names 采用单个宿主环境名称或以逗号分隔的宿主环境名称列表,用于触发已包含内容的呈现。
-->
    <strong>HostingEnvironment.EnvironmentName is Staging or Production</strong>
    this will run in Development <br>

Script and Link Tag Helpers

这两个Tag Helpers使我们在HTML中添加JS和CSS引用更容易;如果我们使用像CDN这样的外部资源,还能使用本地备用的URL地址。 此外,它们大大简化了使用全局模式时引用大量资源文件。 就像image标签助手,Script和Link Tag Helpers也可以帮助我们缓存资源文件。

<!--
 这里src不可用。
<script src="https://cdn.bootcss.com/jquery1/3.3.1/jquery.js"></script>
<script>(window.jQuery && window.jQuery.fn||document.write("\u003Cscript src=\u0022\/lib\/jquery\/dist\/jquery.js\u0022\u003E\u003C\/script\u003E"));</script>
<script src="/lib/jquery/dist/jquery.js"></script>
-->
<script src="https://cdn.bootcss.com/jquery1/3.3.1/jquery.js"
        asp-fallback-src="~/lib/jquery/dist/jquery.js"
        asp-fallback-test="window.jQuery && window.jQuery.fn"></script>

这个例子显示我们引用了来自 aspnetcdn 的 Bootstrap JS文件。如果该网站不可用,将引用本地文件,使用 asp-fallback-src Tag Helper;什么是 asp-fallback-test?它是一种知道是否会使用本地备用的方法,在这个示例中,我们使用一个特定的代码来检查Bootstrap的JS功能是否存在。

如果 asp-fallback-test 中的表达式返回false(falsy),将使用 asp-fallback-src 指定的源文件。

缓存 TagHelper

首先说一下 <cache> Tag Helper。与其它Tag Helper不同,其它Tag Helper被当作属性使用,缓存Tag Helper作为标签使用 - <cache>。它根据其属性指定的选项,将包含的内容缓存到内存中。

expires-after - 最常用的一个,它表示缓存内容过期的时间段(timespan) expires-on - 过期的时间点 expires-sliding – 访问超过某个时间段后就过期(timespan)

vary-by 属性

它基于当前请求的查询参数创建唯一的缓存键。

<cache expires-after="@TimeSpan.FromSeconds(10)" vary-by-query="queryParam1">
    缓存10秒
    this will be cached in server memory. @DateTime.Now.ToString("hh:mm:ss tt")
</cache>

http://localhost:5000/home/cache?queryParam1=1

<h1>10秒比较</h1>
<cache expires-after="@TimeSpan.FromSeconds(10)">
    this will be cached in server memory. @DateTime.Now.ToString("hh:mm:ss tt")
</cache>
<br/>
<span>
    this will be cached in server memory. @DateTime.Now.ToString("hh:mm:ss tt")
</span>



<h1>3个属性比较</h1>
<!--expires-on 过期的时间点-->
<cache expires-on="@DateTime.Today.AddHours(15)">
    this will be cached in server memory. @DateTime.Now.ToString("hh:mm:ss tt")
</cache>
<br/>
<!--expires-after 最常用的一个,它表示缓存内容过期的时间段(timespan)-->
<cache expires-after="@TimeSpan.FromSeconds(10)">
    this will be cached in server memory. @DateTime.Now.ToString("hh:mm:ss tt")
</cache>
<br/>
<!--expires-sliding 每次内容被请求后缓存被延长的时间(timespan)-->
<cache  expires-sliding="@TimeSpan.FromSeconds(10)">
    this will be cached in server memory. @DateTime.Now.ToString("hh:mm:ss tt")
</cache>



<h1>vary-by</h1>
<h2>vary-by-query</h2>
<!-- /home/cache?queryParam1=1 -->
<cache expires-after="@TimeSpan.FromSeconds(10)" vary-by-query="queryParam1">
    缓存10秒
    this will be cached in server memory. @DateTime.Now.ToString("hh:mm:ss tt")
</cache>

<h2>vary-by-route</h2>
<div>接受路由参数名称的逗号分隔列表,用于在路由数据参数值发生更改时触发缓存刷新。</div>

<h2>vary-by-cookie</h2>
<div>根据存储在cookie中的某一个值来创建唯一的缓存,逗号分隔cookie名称列表</div>


<h2>vary-by-header</h2>
<div>基于请求头的某一个参数来创建唯一的缓存,只需要单个请求头名称</div>


<h2>vary-by-user</h2>
<div>指定当已登录用户(或上下文主体)发生更改时是否应重置缓存.</div>

分布式 Cache

为什么我们应该使用分布式缓存?

支持更高的缩放比例(与内存缓存相比) 使用分布式缓存将缓存内存迁移到外部进程 我们在所有的Web服务器上得到一致的数据(用户总是得到相同的结果,无论他们访问到哪台Web服务器) 缓存的数据在服务器重新启动和部署时不会丢失 我们可以停止或添加Web服务器,不会丢失缓存的数据 现在我们谈谈我们前面提到的分布式缓存Tag Helper。

分布式缓存Tag Helper的行为与缓存Tag helper几乎相同。对<cache> Tag Helper提供每一个属性也可用于<distributed-cache> Tag Helper。

但是,Distributed Cache TagHelper的区别在于它使我们能够注入和使用外部缓存管理器,而不是使用默认的内存缓存管理器。

如果您需要将缓存的HTML内容存储在用SQL Server、Redis等分布式缓存中,那么您需要<distributed-cache> Tag Helper。

ASP.NET Core MVC提供两个缓存管理器的实现,分别是SQL Server和Redis。

另一个分布式缓存需要注意的是,它需要一个name属性。

参考:http://www.cnblogs.com/tdfblog/p/caching-taghelpers-in-asp-net-core-mvc.html https://docs.microsoft.com/zh-cn/aspnet/core/mvc/views/tag-helpers/built-in/distributed-cache-tag-helper?view=aspnetcore-2.1

表单

Form

<form asp-controller="Demo" asp-action="Register" method="post">
    <!-- Input and Submit elements -->
</form>

生成的HTML

<form method="post" action="/Demo/Register">
    <!-- Input and Submit elements -->
    <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>" />
</form>

请注意在HTTP Post操作方式中,RequestVerificationToken 与内置的[ValidateAntiForgeryToken]属性一起工作,同时,该请求方法会被标记为post方式。

Form Tag Helper的还提供了 asp-route-{ParameterName} 属性,其中参数名称为被添加到路由的值;并且还提供了@Html.BeginForm@Html.BeginRouteForm另一种清晰的替代方式。

Input

这一个很简单,它是@Html.EditorFor(m => m.Name)的替代方式。

Lable

这一个也很简单,它是@Html.LabelFor(m => m.Name)的替代方式。 它与输入框Tag Helper配合使用:

 <input asp-for="Name" />
    <label asp-for="Name" />

定义两个类

public class AddressViewModel
{
	public string AddressLine1 { get; set; }
}

public class RegisterAddressViewModel
{
	[Required]
	[MinLength(50)]
	[MaxLength(200)]
	public string Description { get; set; }
		
	[Display(Name = "Register Email")]
	public string Email { get; set; }

	[DataType(DataType.Password)]
	public string Password { get; set; }

	public AddressViewModel Address { get; set; }
}

TextArea

<textarea asp-for="Description"></textarea><br />

生成

<textarea data-val="true" data-val-maxlength="The field Description must be a string or array type with a maximum length of ''200''." data-val-maxlength-max="200" data-val-minlength="The field Description must be a string or array type with a minimum length of ''50''." data-val-minlength-min="50" data-val-required="The Description field is required." id="Description" name="Description"></textarea>

Validation

我们使用Validation Tag Helper为我们的视图模型的属性显示验证消息,使用方式也很简单:

<span asp-validation-for="Name"></span>

生成

<spandata-valmsg-for="Name" data-valmsg-replace="true"></span>

综合例子

@model RegisterAddressViewModel

<form asp-controller="Demo" asp-action="RegisterAddress" method="post">
    <label asp-for="Email"></label> :  <input asp-for="Email" /> <br />
    <label asp-for="Password"></label>: <input asp-for="Password" /> <br /><span asp-validation-for="Password"></span><br />
    <label asp-for="Address"></label>: <input asp-for="Address.AddressLine1" /><br />
    <textarea asp-for="Description"></textarea><br />
    <button type="submit">Register</button>
</form>

生成

<form method="post" action="/Demo/RegisterAddress" novalidate="novalidate">
    <label for="Email">Register Email</label> :  <input type="text" id="Email" name="Email" value=""> <br>
    <label for="Password">Password</label>: <input type="password" data-val="true" data-val-required="The Password field is required." id="Password" name="Password"> <br><spandata-valmsg-for="Password" data-valmsg-replace="true"></span><br>
    <label for="Address">Address</label>: <input type="text" id="Address_AddressLine1" name="Address.AddressLine1" value=""><br>
    <textarea data-val="true" data-val-maxlength="The field Description must be a string or array type with a maximum length of ''200''." data-val-maxlength-max="200" data-val-minlength="The field Description must be a string or array type with a minimum length of ''50''." data-val-minlength-min="50" data-val-required="The Description field is required." id="Description" name="Description"></textarea><br>

    <button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8E8SUbZpCkNIprGBJ28vOqxP8Qqc_XkuoKoGsVS2b7N-WBCS68EFGRFQBcZRARdNip0nQw45i8zy4f5XYlA1WGbaeEvYY7GDPwtM0bbjUZSHEAHEptxRzGMSXzIzyBnKkQLtvZkdjBhF5zX6VoBke38"></form>

自定义 Tag Helpers

通过创建自定义Tag Helpers,我们可以扩展现有元素或创建我们自己的元素。 Tag Helper是实现ITagHelper接口类的统称。MVC为我们提供了该接口的抽象类TagHelper,它位于 Microsoft.AspNetCore.Razor.Runtime 程序集中。因此,我们可以直接从TagHelper类继承,我们主要需要实现以下方法:

  public virtual void Process(TagHelperContext context, TagHelperOutput output);

  public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output);

Process方法是具体的逻辑实现。它需要传递 Tag Helper上下文的实例和Tag Helper输出(我们可以用它来读取和更改Tag Helper范围内的实际内容)

简单示例

我们创建自己的Tag Helper。假设我们将使用<simple> </simple>Tag Helper,其中的内容将是粗体。

我们将要创建一个名为CustomTagHelpers的新项目。因此,程序集名称也将是 CustomTagHelpers。

首先,我们创建一个新的Tag Helper。使用Visual Studio,我们可以这样操作添加 - > 新建项 - > Web - > Razor 标记帮助器。

这是默认生成的代码:

    public class SimpleTagHelper : TagHelper
    {
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            output.TagName = "strong";          
        }
    }

为了能够在我们的视图中使用新创建的Tag Helper,我们必须在 ViewImports.cshtml 文件中添加下面这一行:

@using IdentityDemo2
@using IdentityDemo2.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper "*, IdentityDemo2"

以上代码我们使用了通配符表明所有的 tag helper 都将在我们的程序集中启用。 @addTagHelper 之后的第一个字符串指明了要加载的 tag helper(我们使用 "*" 代表所有 tag helper ), 第二个字符串 “IdentityDemo2” 指明了此 tag helper 所在的程序集。除此之外要注意的是, 使用通配符的第二行,引入了 ASP.NET Core MVC 的 tag helper(这些辅助类在 Tag Helpers 介绍中已经讨论过)。 是 @addTagHelper 命令使 tag helper 在 Razor 视图中起作用的。你还可以提供如下所示的 tag helper 的全名(FQN):

<div>
    <Simple>2.simple.你是天边的亿朵元</Simple>
</div>

我们将在Visual Studio中看到这个simple 的标签已经变成紫色,并且被识别为Tag Helper。如果我们运行应用程序,我们将以粗体显示此文本。

如果我们查看HTML输出,我们可以看到simple 标签被strong所替代:

<div>
    <strong>2.simple你是天边的亿朵元</strong>
</div>

改变属性,构建一个 Email 标签

  public class EmailTagHelper : TagHelper
    {
        private const string EmailDomain = "contoso.com";

        // Can be passed via <email mail-to="..." />. 
        // Pascal case gets translated into lower-kebab-case.
        public string MailTo { get; set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            output.TagName = "a";    // Replaces <email> with <a> tag

            var address = MailTo + "@" + EmailDomain;
            output.Attributes.SetAttribute("href", "mailto:" + address);
            //output.Content.SetContent(address);
        }
    }

例如:

<email>Support</email>

生成

<a href="mailto:@contoso.com">Support</a>

资料:

Sweet-Tang,ASP.NET Core MVC – Tag Helpers 介绍 Form tagHelper,窗体中使用TagHelpers 作者:Rick Anderson,翻译:张海龙(jiechen),自定义辅助类标签 Email

ASP.NET Core 3.0 : 二十五. TagHelper

ASP.NET Core 3.0 : 二十五. TagHelper

  什么是TagHelper?这是ASP.NET Core 中新出现的一个名词,它的作用是使服务器端代码可以在Razor 文件中参与创建和呈现HTML 元素。(ASP.NET Core 系列目录)

一、概述

  上面的解释有点拗口?那么换一个名词,HtmlHelper大家都知道吧,在ASP.NET Core中,TagHelper类似HtmlHelper,但可以说是青出于蓝而胜于蓝。那么TagHelper的作用也就大概明白了吧。

首先通过一个例子看一下TagHelper是怎么使用的,看看它和HtmlHelper有什么区别。新建一个Book类:

public class Book
    {
        [Display(Name = "编号")]
        public string Code { get; set; }
[Display(Name = "名称")]
        public string Name { get; set; }
    }

新建对应的Controller和Action:

public class BookController : Controller
    {
        // GET: /<controller>/
        public IActionResult Index()
        {
            return View(new Book() { Code = "001", Name = "ASP" });
        }
    }

最后就是View了:

@model Book
@{
    Layout = null;
}
@Html.LabelFor(m => m.Name)
@Html.EditorFor(m => m.Name)
<br />
<label asp-for="Name"></label>
<input asp-for="Name" />

这里分别通过HtmlHelper和TagHelper两种方式实现了一个文本和输入框的显示。查看网页源代码,可以看到二者生成的HTML如下:

<label for="Name">Name</label>
<input class="text-box single-line" id="Name" name="Name" type="text" value="ASP" />
<br/>
<label for="Name">Name</label>
<input type="text" id="Name" name="Name" value="ASP" />

目前看起来二者差不多,从工作量上来看也是区别不大。现在功能实现了,需要做一些样式处理。简单举个例子,现在希望Book的编号(Code)对应的label的颜色设置为红色,定义了一个css如下:

<style type="text/css">
    .codeColor {
        color:red;
    }
</style>

然后准备把这个样式应用到label上,这时如果是HtmlHelper就很有可能会被问:“class写在哪”,估计好多人都被问过。然后我们告诉他可以这样写:

@Html.LabelFor(m=>m.Name,new {@class="codeColor"})

前端工程师添加后达到了想要的效果,但同时表示记不住这个写法,下次可能还会问。

如果是TagHelper就方便了,告诉他可以像平时给Html的标签添加class一样操作即可,也就是:

<label asp-for="Name" class="codeColor"></label>

前端工程师表示这种写法“真是太友好了”。同样对于Form及验证,比较一下两种写法的不同,HtmlHelper版:

@using (Html.BeginForm("Index", "Home", FormMethod.Post)){    
@Html.LabelFor(m => m.Code)
    @Html.EditorFor(m => m.Code)    @Html.ValidationMessageFor(m => m.Code)    <input type="submit" value="提交" />
}

TagHelper版:

<form asp-action="Index" asp-controller="Home" method="post">
    <label asp-for="Code"></label>
    <input asp-for="Code" />
    <span asp-validation-for="Code"></span>
    <input type="submit" value="提交" />
</form>

二、自定义TagHelper

现在有这样的需求,用于显示Book的编号的label不止要添加名为codeColor的css样式,还要给书的编号自动添加一个前缀,例如“BJ”。

对于这样的需求,希望可以通过一个简单的标记,然后由TagHelper自动实现。例如:

<label show-type="bookCode">1001</label>

自定义了一个属性“show-type”,用于标识这个label的显示类别,“1001”为假定的图书编号。通过这样的设置方式,将来如果需求有变化,需要对编号的显示做更多的修饰,只需修改对应的TagHelper即可,而页面部分不需要做任何调整。

系统提供了方便的自定义TagHelper的方式,就是继承系统提供的TagHelper类,并重写它的Process/ProcessAsync方法,例如下面的例子:

public class LabelTagHelper : TagHelper
    {
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            if (output.Attributes.TryGetAttribute("show-type", out TagHelperAttribute showTypeAttribute))
            {
                if (showTypeAttribute.Value.ToString().Equals("bookCode"))
                {
                    output.Attributes.SetAttribute("class", "codeColor");

                    string content = output.Content.IsModified ? output.Content.GetContent() : (await output.GetChildContentAsync()).GetContent(); ;
                    output.Content.SetContent("BJ" + content);
                }
            }
        }
    }

首先判断label是否被设置了show-type="bookCode",然后获取当前label的Content内容,将其添加前缀“BJ”后作为此label的Content的新内容。注意一下Content的获取方式,如果它没有被修改,凭感觉直接通过output.Content.GetContent()获取到的内容是空的。

访问index页面,可以看到改标签已被处理,如下图:

备注:a.关于获取show-type的值,还可以有其他方式,下文会讲到。

b.从规范化命名的角度,建议将自定义的TagHelper其命名为XXXagHelper这样的格式。

三、TagHelper的注册

TagHelper自定义之后需要将其注册一下,否则它是不会生效的。打开_ViewImports.cshtml,默认为:

@using TagHelperDemo
@using TagHelperDemo.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

在最下面添加一条

@addTagHelper *, TagHelperDemo

最后添加的这一句话是什么意思呢?也就是将程序集TagHelperDemo(即第二个参数)中的所有TagHelper(第一个参数为“*”,即所有)全部启用。假如还定义了一个PasswordTagHelper,但只想只添加LabelTagHelper,可以这样写:

@addTagHelper TagHelperDemo.TagHelpers. LabelTagHelper, TagHelperDemo

如果想添加所有自定义的TagHelper,但要去除LabelTagHelper呢?

那么可以先添加所有,再去除这个LabelTagHelper。

@addTagHelper *, TagHelperDemo
@removeTagHelper TagHelperDemo.TagHelpers. LabelTagHelper, TagHelperDemo

四、TagHelper的作用范围

在项目中,可能不止使用label标签来显示Book的Code,还有可能会是p、span等类型的标签,现在的需求是,无论是上述哪一种标签,都要实现添加css和前缀的功能。

现在将index.cshtml中新增一个p标签如下:

<p show-type="bookCode">1002</p>

访问这个页面发现1002未被处理。这是因为我们定义的TagHelper名为LabelTagHelper,在默认的情况下只会处理label标签。当然也可以做特殊设置,例如下面代码的写法:

[HtmlTargetElement("p")]
    public class LabelTagHelper : TagHelper
    {
      //代码省略
    }

通过“[HtmlTargetElement("p")]”指定本TagHelper只能被使用于p标签。再次访问此页面,发现p标签被处理了,而label未被处理。这说明这样的显式指定的优先级要高于默认的名称匹配。除了设置指定标签,还可以有一些其他的辅助设置:

[HtmlTargetElement("p", Attributes = "show-type", ParentTag = "div")]
public class LabelTagHelper : TagHelper

可以这样写,会匹配p标签,要求该标签拥有show-type属性,并且父标签为div。这几个条件是“and”的关系。如果还想匹配label标签,可以添加对label的设置,例如下面代码这样:

[HtmlTargetElement("p", Attributes = "show-type", ParentTag = "div")]
[HtmlTargetElement("label", Attributes = "show-type", ParentTag = "div")]
public class LabelTagHelper : TagHelper

这两个HtmlTargetElement的关系是“or”。通过这样的设置,可以极大的缩小目标标签的范围。

但是这样设置之后,这个TagHelper的名字再叫LabelTagHelper就不合适了,例如可以改为BookCodeTagHelper,最终代码如下:

[HtmlTargetElement("p", Attributes = "show-type", ParentTag = "div")]
[HtmlTargetElement("label", Attributes = "show-type", ParentTag = "div")]
public class BookCodeTagHelper : TagHelper
{
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        if (output.Attributes.TryGetAttribute("show-type", out TagHelperAttribute showTypeAttribute))
        {
            if (showTypeAttribute.Value.ToString().Equals("bookCode"))
            {
                output.Attributes.SetAttribute("class", "codeColor");

                string content = output.Content.IsModified ? output.Content.GetContent() :
                                    (await output.GetChildContentAsync()).GetContent(); ;
                output.Content.SetContent("BJ" + content);
            }
        }
    }
}

如果想使个别Html标签屏蔽TagHelper的作用,可以使用“!”。例如下面两个标签:

<!label show-type="bookCode">1001</label>

五、自定义标签

上一节最终形成了一个名为BookCodeTagHelper的TagHelper,我们知道LabelTagHelper是可以按名称默认匹配label标签的,那么是否可以自定义一个BookCode标签呢?在index.cshtml中添加这样的代码:

<BookCode>1003</BookCode>

 

由于自定义bookcode标签的目的就是专门显示Book的Code,所以也不必添加show-type属性了。然后修改BookCodeTagHelper,修改后的代码如下:

public class BookCodeTagHelper : TagHelper
{
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        output.Attributes.SetAttribute("class", "codeColor");

        string content = output.Content.IsModified ? output.Content.GetContent() :
                            (await output.GetChildContentAsync()).GetContent(); ;
        output.Content.SetContent("BJ" + content);
    }
}

 

去掉了两个HtmlTargetElement设置并取消了对show-type的判断,访问index页面查看新建的bookcode标签是否会被处理,结果是没有被处理。这是为什么呢?

这是由于TagHelper会将采用Pascal 大小写格式的类和属性名将转换为各自相应的短横线格式。即“BookCode”对应“book-code”,获取标签的属性值,同样遵循这样的规则。所以将标签改为如下写法即可:

<book-code>1003</book-code>

再次运行测试,发现这个新标签被成功处理。查看网页源代码,被处理后的Html代码是这样的:

<book-code class="codeColor">TJ1003</book-code>

如果想将其改变为label,可以在BookCodeTagHelper中通过指定TagName实现:

public class BookCodeTagHelper : TagHelper
{
    public Book Book { get; set; }
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "label";
        output.Attributes.SetAttribute("class", "codeColor");

        string content = output.Content.IsModified ? output.Content.GetContent() :
                            (await output.GetChildContentAsync()).GetContent(); ;
        output.Content.SetContent(Book.Prefix + content);
    }
}

六、TagHelper与页面之间的数据传递

假如现在的新需求是图书编码的前缀不再固定为“BJ”了,需要在标签中定义,例如这样:

<book-code prefix="SH">1003</book-code>

需要获取prefix的值,在上面的例子中采用的是TryGetAttribute方法,其实还有简单的方式,修改BookCodeTagHelper,代码如下:

public class BookCodeTagHelper : TagHelper
    {
        public string Prefix { get; set; }
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            output.Attributes.SetAttribute("class", "codeColor");

            string content = output.Content.IsModified ? output.Content.GetContent() :
                                (await output.GetChildContentAsync()).GetContent(); ;
            output.Content.SetContent(Prefix + content);
        }
    }

标签中的prefix的值会自动赋值给BookCodeTagHelper.Prefix,是不是更方便了。那么如果是Model中的值呢?假如Book类有一个属性“public string Prefix { get; set; } ”,这和传入一个字符串没什么区别,那么可以这样写:

<book-code prefix="@Model.Prefix">1003</book-code>

这种传值方式不止是支持字符串,将Model整体传入也是支持的,将标签修改如下:

<book-code book="@Model">1003</book-code>

修改BookCodeTagHelper代码:

public class BookCodeTagHelper : TagHelper
    {
        public Book Book { get; set; }
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            output.Attributes.SetAttribute("class", "codeColor");

            string content = output.Content.IsModified ? output.Content.GetContent() :
                                (await output.GetChildContentAsync()).GetContent(); ;
            output.Content.SetContent(Book.Prefix + content);
        }
    }

七、取消标签输出

前面的几个例子都是对满足条件的标签的修改,TagHelper也可以取消对应标签的输出,例如存在这样一个标签:

<div simple-type="Simple1"></div>

如果不想让它出现在生成的Html中,可以这样处理:

[HtmlTargetElement("div",Attributes = "simple-type")]
public class Simple1TagHelpers : TagHelper
{
    public string SimpleType { get; set; }
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        if (SimpleType.Equals("Simple1"))  //可以是其他一些判断规则
        {
            output.SuppressOutput();
        }
    }
}

八、TagBuilder

在TagHelper中,可以用TagBuilder来辅助生成标签,例如存在如下两个div:

<div simple-type="Simple2"></div>
<div simple-type="Simple3"></div>

想在div中添加Html元素可以这样写:

[HtmlTargetElement("div",Attributes = "simple-type")]
public class Simple1TagHelpers : TagHelper
{
    public string SimpleType { get; set; }
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        if (SimpleType.Equals("Simple2"))
        {
            output.Content.SetHtmlContent("<p>Simple2</p>");
        }
        else if (SimpleType.Equals("Simple3"))
        {
            var p = new TagBuilder("p");
            p.InnerHtml.Append("Simple3");
            output.Content.SetHtmlContent(p);
        }
    }
}

通过TagBuilder生成了一个新的p标签,并将它插入到div中。

 

原文出处:https://www.cnblogs.com/FlyLolo/p/ASPNETCore_25.html

我们今天的关于asp.net-core – TagHelper,用于将路由值作为链接的一部分传递asp.net mvc路由机制的分享已经告一段落,感谢您的关注,如果您想了解更多关于.Net Core 3.1 TagHelper的使用、.NET Core MVC下的TagHelper、asp.net core 2.1 TagHelpers、ASP.NET Core 3.0 : 二十五. TagHelper的相关信息,请在本站查询。

本文标签: