前一篇中老周从标记帮助的底层介绍关键性的接口,如 ITagHelper ,它是一个标志,用于识别哪些类属于 Tag Helper。

标记帮助器毕竟是针对 HTML 标记的,所以得筛选。说白了就是我写的这个帮助器在哪些 HTML 标记上起作用。这就需要拿出一个特性类。

  1. [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
  2. public sealed class HtmlTargetElementAttribute : Attribute

咱们看到,这个特性只能应用到类上面。啥类?当然是从 TagHelper 派生的类(或者实现 ITagHelper 接口的类)。

在使用时,我们一般会调用带一个字符串参数的构造函数。

  1. public HtmlTargetElementAttribute(string tag)

用字符串说明你这个帮助器用到哪个标记上。比如

  1. [HtmlTargetElement("div")]
  2. [HtmlTargetElement("a")]
  3. [HtmlTargetElement("p")]
  4. [HtmlTargetElement("form")]

这个应该好理解,如果设置的是“div”,表明我这个帮助器是在<div>元素上起作用的。

当然,这个特性类也有无参数的构造函数。如果调用此构造函数,即未指定 HTML 标记。

  1. [HtmlTargetElement]

这相当于把标记指定为“*”(星号)。

  1. [HtmlTargetElement("*")]

意思就是我这个帮助器是面向所有 HTML 元素的,通吃。

也许各位大伙伴也发现了,这厮筛选元素的方式很像 CSS 的选择器。对,的确是的。但是,得记住:这货是面向标记的,而不是特定某个元素的。啥意思?就是说你不能用元素 id 去筛选,比如这样就不行。

  1. [HtmlTargetElement("#abc")]

不过,可以根据属性筛选,比如

[HtmlTargetElement("span", Attributes = "[data=1]")]

属性筛选要放在 Attributes 属性上,不要和标记名称写一起。上面代码是筛选有 data = "1" 的span标记。即

  1. <span data="1">...</span>

----------------------------------------------------------------------------------------------------------

好了,概念的东西说得有点多了,咱们来做个例子。

这里老周写了一个面向 <span> 的标记帮助器,把此标记的内容中带有中括号的文本掩盖掉。比如

  1. <span>我是一只小小[小鸟]</span>

被中括号裹起来的是“小鸟”,所以把它掩盖掉,变成“我是一只小小**”,或“我是一只小小##”。

标记帮助器代码如下:

  1. namespace Test;
  2.  
  3. [HtmlTargetElement("span")]
  4. public class ReplaceCharTagHelper : TagHelper
  5. {
  6. public char MaskChar { get; set; } = '*';
  7.  
  8. public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
  9. {
  10. // 下面这行代码的作用是让标记执行它的子级
  11. // 这样我们才能获取到目标元素的内容
  12. var tagContent = await output.GetChildContentAsync();
  13. string text = tagContent.GetContent();
  14. int count = text.Length;
  15. if(count > 0)
  16. {
  17. // 原字符串的索引不能set,因此先转为char数组
  18. var chararr = text.ToArray();
  19. // 这个bool变量是个开关
  20. // 即遇到“[”字符时开,遇到“]”字符时关
  21. // 后面在替换字符时用得上
  22. bool flag = false;
  23. for(int x = 0; x < count; x++)
  24. {
  25. char c = chararr[x];
  26. if(c == '['){
  27. flag = true; //开
  28. continue;
  29. }
  30. else if(c == ']')
  31. {
  32. flag = false; //关
  33. continue;
  34. }
  35. if(flag){
  36. // 如果“开”说明进入了中括号内,表示字符可替换
  37. // 如果“关”说明已经出了中括号,就别替换了
  38. chararr[x] = MaskChar;
  39. }
  40. }
  41. // 构建新的字符串
  42. string newStr = new string(chararr);
  43. // 把“[”、“]”两个字符清除
  44. newStr = newStr.Replace("[", "").Replace("]", "");
  45. // 用新的内容替换标记原来的内容
  46. output.Content.SetContent(newStr);
  47. }
  48. }
  49. }

下面老周解释一下。

1、这个帮助器是面向<span>元素的。

2、MaskChar 属性允许咱们自己设置掩盖文本的字符,算是一掩码吧。

3、在处理HTML输出时注意这一句:

  1. var tagContent = await output.GetChildContentAsync();

为什么要调用这一句呢?因为咱们要修改<span>与</span>之间的内容,你如果直接访问 output.Content.GetContent 是什么也获取不到的,因为此时<span>的子级内容还没有呈现。所以啊,为了能获取到待处理的文本,咱们要先调用 GetChildContentAsync 方法。这个方法会先执行子级内容,然后返回内容。

4、这里老周的处理思路是这样的。string 类型的实例虽然是 char 的集合,但其索引器是 get 的,不支持 set,即咱们不能直接修改其中某个字符。办法只能先 ToArray 让文本变成 char[],然后循环里面每个字符。如果遇到“[”,表明中括号开始了(把 flag 设为 true),从下一个字符起就是中括号包含的内容,需要掩盖掉;如果遇到“]”字符,说明要离开中括号的包围圈(flag 设为 false),从下一个字符起就不是中括号中的字符,不能掩盖。最后,用修改过的 char[] 产生新的字符串对象,为了打扫战场,还要把“[”、“]”去掉。这个直接用 Replace 就行了。

5、调用 output.Content.SetContent 方法用新的内容替换原有的内容。

在 Razor 文档中,用 @addTagHelper 指令导入刚自定义的标记帮助器。

  1. @addTagHelper Test.ReplaceCharTagHelper, TestApp

这里 TestApp 是标记帮助器所在程序集的名称,一般与项目名字相同。我这个项目就叫 TestApp。

来,测试一下。

  1. @page
  2. @addTagHelper Test.ReplaceCharTagHelper, TestApp
  3.  
  4. <span mask-char="@('#')">
  5. 明天我们去[骑行]
  6. </span>
  7.  
  8. <span mask-char="@('*')">
  9. ,顺便买几吨[啤酒]喝
  10. </span>

mask-char 就是类中定义的 MaskChar 属性,ASP.NET Core 会识别像 mask-char 这样的写法,主要是语义明了。在设置 MaskChar 属性时要把值写在 @( ) 中,不能写成 mask-char="*",否则编译不通过的。="*" Razor 引擎默认解析为 string 类型而不是 char,而写在 @() 中就成了 C# 表达式,编译器能识别。

运行后的结果如下。

咱们也可以让标记帮助器支持更多元素。

  1. [HtmlTargetElement("span")]
  2. [HtmlTargetElement("div")]
  3. [HtmlTargetElement("p")]
  4. public class ReplaceCharTagHelper : TagHelper

【ASP.NET Core】标记帮助器——元素筛选的更多相关文章

  1. ASP.NET Core利用拦截器 IActionFilter实现权限控制

    “麦荻网教系统”采用了前后端代码分离的架构,即“Miidy.Cloud.Console”站与“Miidy.Cloud.Manage”站(两个前端站)同时通过web api的方式调用“Miidy.Clo ...

  2. 重学ASP.NET Core 中的标记帮助程序

    标记帮助程序是什么 标记帮助程序使服务器端代码可以在 Razor 文件中参与创建和呈现 HTML 元素. 例如,内置的 ImageTagHelper 可以将版本号追加到图片名称.  每当图片发生变化时 ...

  3. 【目录】asp.net core系列篇

    随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...

  4. C# -- HttpWebRequest 和 HttpWebResponse 的使用 C#编写扫雷游戏 使用IIS调试ASP.NET网站程序 WCF入门教程 ASP.Net Core开发(踩坑)指南 ASP.Net Core Razor+AdminLTE 小试牛刀 webservice创建、部署和调用 .net接收post请求并把数据转为字典格式

    C# -- HttpWebRequest 和 HttpWebResponse 的使用 C# -- HttpWebRequest 和 HttpWebResponse 的使用 结合使用HttpWebReq ...

  5. asp.net core系列 68 Filter管道过滤器

    一.概述 本篇详细了解一下asp.net core filters,filter叫"筛选器"也叫"过滤器",是请求处理管道中的特定阶段之前或之后运行代码.fil ...

  6. 用ASP.NET Core 2.1 建立规范的 REST API -- HATEOAS

    本文所需的一些预备知识可以看这里: http://www.cnblogs.com/cgzl/p/9010978.html 和 http://www.cnblogs.com/cgzl/p/9019314 ...

  7. ASP.Net Core开发(踩坑)指南

    ASP.NET与ASP.NET Core很类似,但它们之间存在一些细微区别以及ASP.NET Core中新增特性的使用方法,在此之前也写过一篇简单的对比文章ASP.NET MVC应用迁移到ASP.NE ...

  8. 在Asp.NET Core中如何优雅的管理用户机密数据

    在Asp.NET Core中如何优雅的管理用户机密数据 背景 回顾 在软件开发过程中,使用配置文件来管理某些对应用程序运行中需要使用的参数是常见的作法.在早期VB/VB.NET时代,经常使用.ini文 ...

  9. 在Mac上开发使用yeoman构建Asp.net core项目并且实现分层引用

    1.Yeoman? yeoman是一个自动化脚手架工具.它提供很多generator,generator相当于VisualStudio的模板,用来初始化项目.更多的就不多说了,写一遍都写不完,自己看吧 ...

  10. yoeman构建Asp.net core项目并且实现分层

    在Mac上开发使用yoeman构建Asp.net core项目并且实现分层引用 1.Yoeman? yoeman是一个自动化脚手架工具.它提供很多generator,generator相当于Visua ...

随机推荐

  1. NET 6 实现滑动验证码(一)、创建工程

    目录 实现滑动验证码的目的 创建.NET 6工程 实现滑动验证码的目的 传统验证码实现起来比较简单,但在OCR技术越来越成熟的情况下,验证码的破解难度越来越低,但如果将验证码难度加高(各种干扰背景,扭 ...

  2. 如何使用zx编写shell脚本

    前言 在这篇文章中,我们将学习谷歌的zx库提供了什么,以及我们如何使用它来用Node.js编写shell脚本.然后,我们将学习如何通过构建一个命令行工具来使用zx的功能,帮助我们为新的Node.js项 ...

  3. 《Hierarchical Text-Conditional Image Generation with CLIP Latents》阅读笔记

    概括 模型总述 本篇论文主要介绍DALL·E 2模型,它是OpenAI在2022年4月推出的一款模型,OpenAI在2021年1月推出了DALL·E模型,2021年年底推出了GLIDE模型. DALL ...

  4. Spring02:注解IOC、DBUtils单表CRUD、与Junit整合

    今日内容:基于注解的IOC及IOC的案例 Spring中IOC的常用注解 案例-使用xml方式和注解方式实现单表的CRUD操作 持久层技术选型:DBUtils 改造基于注解的IOC案例,使用纯注解的方 ...

  5. placeholder属性作用

    placeholder属性作用 1.介绍 该提示会在输入字段为空时显示,并会在字段获得焦点时消失. 注释:placeholder 属性适用于以下的 <input> 类型:text, sea ...

  6. 解决.net Core中WebApi自动Model验证导致数据格式不能统一

    简言: 最近做项目用WebAPI Core时,想把返回数据的格式,统一弄成:{"errorMsg":"xxx","Data":"x ...

  7. python函数及算法

    算法二分法 二分算法图 什么是算法? ​ 算法是高效解决问题的办法. 需求:有一个按照从小到大顺序排列的数字列表,查找某一个数字 # 定义一个无序的列表 nums = [3,4,5,67,8,9,12 ...

  8. STM32基本定时器控制LED闪烁代码

    led.c #include "led.h" void LED_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2P ...

  9. SQLMap入门——判断文本中的请求是否存在注入

    从文件中加载HTTP请求,SQLMap可以从一个文本文件中获取HTTP请求,这样就可以不设置其他参数(如cookie.POST数据等),txt文件中的内容为Web数据包 文本文件如图(请求数据可以通过 ...

  10. js 中常用函数汇总(含示例)

    〇.前言 js 在日常开发中还是比较常用的,本文将常用的 js 方法简单汇总一下,希望对你我有一点帮助. 一.重复 / 延迟操作 1.设置固定时间间隔,重复执行(setInterval(funcRef ...