【ASP.NET Core】标记帮助器——元素筛选

asp,net,core,标记,帮助,元素,筛选 · 浏览次数 : 233

小编点评

**老周的帮助器代码解析** 该代码实现了一个面向 <span> 元素的标记帮助器,用于掩盖标记中包含的字符。 **主要功能:** 1. 定义一个名为 `MaskChar` 的属性,用于存储掩盖字符。默认值为 '*'。 2. 在处理 HTML 输出时,获取标记中所有字符的字符串。 3. 如果字符数量大于 0,则将其转换为字符数组,并循环遍历字符。 4. 在遍历过程中,根据字符类型进行替换: - 如果遇到 "["字符,将其视为中括号开始。 - 如果遇到 "]"字符,将其视为中括号结束。 5. 将修改后的字符数组转换为字符串并替换原始字符串。 6. 使用 `output.Content.SetContent()` 方法将新的字符串设置到 HTML 输出中。 **示例:** ```html ``` 这段代码将把 "##" 替换为 "#"。 **其他细节:** - 帮助器的类必须继承 `TagHelper` 类。 - 帮助器可以使用 `[HtmlAttributeName]` 属性指定元素的属性名称。 - 帮助器可以使用 `[Template]` 属性定义元素的模板。 - 帮助器可以使用 `[Display]` 属性指定元素的显示方式。

正文

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

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

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

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

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

public HtmlTargetElementAttribute(string tag)

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

[HtmlTargetElement("div")]
[HtmlTargetElement("a")]
[HtmlTargetElement("p")]
[HtmlTargetElement("form")]

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

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

[HtmlTargetElement]

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

[HtmlTargetElement("*")]

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

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

[HtmlTargetElement("#abc")]

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

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

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

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

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

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

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

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

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

标记帮助器代码如下:

namespace Test;

[HtmlTargetElement("span")]
public class ReplaceCharTagHelper : TagHelper
{
    public char MaskChar { get; set; } = '*';

    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        // 下面这行代码的作用是让标记执行它的子级
        // 这样我们才能获取到目标元素的内容
        var tagContent = await output.GetChildContentAsync();
        string text = tagContent.GetContent();
        int count = text.Length;
        if(count > 0)
        {
            // 原字符串的索引不能set,因此先转为char数组
            var chararr = text.ToArray();
            // 这个bool变量是个开关
            // 即遇到“[”字符时开,遇到“]”字符时关
            // 后面在替换字符时用得上
            bool flag = false;
            for(int x = 0; x < count; x++)
            {
                char c = chararr[x];
                if(c == '['){
                    flag = true;    //
                    continue;
                }
                else if(c == ']')
                {
                    flag = false;   //
                    continue;
                }
                if(flag){   
                    // 如果“开”说明进入了中括号内,表示字符可替换
                    // 如果“关”说明已经出了中括号,就别替换了
                    chararr[x] = MaskChar;
                }
            }
            // 构建新的字符串
            string newStr = new string(chararr);
            // 把“[”、“]”两个字符清除
            newStr = newStr.Replace("[", "").Replace("]", "");
            // 用新的内容替换标记原来的内容
            output.Content.SetContent(newStr);
        }
    }
}

下面老周解释一下。

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

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

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

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 指令导入刚自定义的标记帮助器。

@addTagHelper Test.ReplaceCharTagHelper, TestApp

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

来,测试一下。

@page
@addTagHelper Test.ReplaceCharTagHelper, TestApp

<span mask-char="@('#')">
    明天我们去[骑行]
</span>

<span mask-char="@('*')">
    ,顺便买几吨[啤酒]喝
</span>

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

运行后的结果如下。

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

[HtmlTargetElement("span")]
[HtmlTargetElement("div")]
[HtmlTargetElement("p")]
public class ReplaceCharTagHelper : TagHelper

 

与【ASP.NET Core】标记帮助器——元素筛选相似的内容:

【ASP.NET Core】标记帮助器——元素筛选

前一篇中老周从标记帮助的底层介绍关键性的接口,如 ITagHelper ,它是一个标志,用于识别哪些类属于 Tag Helper。 标记帮助器毕竟是针对 HTML 标记的,所以得筛选。说白了就是我写的这个帮助器在哪些 HTML 标记上起作用。这就需要拿出一个特性类。 [AttributeUsage(

【ASP.NET Core】标记帮助器——替换元素名称

标记帮助器不仅可以给目标元素(标记)插入(或修改)属性,插入自定义的HTML内容,在某些需求中还可以替换原来标记的名称。 比如我们在使用 Blazor 时很熟悉的 Component 标记帮助器。在 Razor 文档中你将使用 元素来设置要呈现的组件。而在实际处理时,会去掉

【ASP.NET Core】标记帮助器——抽象层

标记帮助器,即 Tag Helpers。这个嘛,就直接翻译了,叫“标记帮助器”,虽然不好听,但只能这样了。当然你翻译为“标记增强器”也行。 所谓标记帮助器,就是针对 HTML 标签(不管是标准的还是自己命名的)进行扩展的做法。它是以 Razor 为基础的,服务于开发人员的。在服务器端用 C# 代码来

ASP.NET Core 8 预览版 4的重大更新

最新版本的 .NET 8 预览版 4 对 ASP.NET Core 进行了重大改进。值得注意的增强功能包括 Blazor 的流式呈现和表单处理、在最小 API 中扩展对表单绑定的支持、用于提高性能的NativeAOT 编译、使用标识 API 终结点增强的身份验证和授权,以及添加用于应用程序监视的指标

[翻译].NET 8 的原生AOT及高性能Web开发中的应用[附性能测试结果]

随着 .NET 8 的发布,微软迈出了重要一步,为 ASP.NET Core 引入了原生的 Ahead-of-Time (AOT) 编译。这一进步不仅提高了应用程序的性能,还简化了开发过程,标志着 .NET 生态系统进入了新的时代。

NET9 AspnetCore将整合OpenAPI的文档生成功能而无需三方库

OpenAPI 规范是用于描述 HTTP API 的标准。该标准允许开发人员定义 API 的形状,这些 API 可以插入到客户端生成器、服务器生成器、测试工具、文档等中。尽管该标准具有普遍性和普遍性,但 ASP.NET Core 在框架内默认不提供对 OpenAPI 的支持。 当前 ASP.NET

ASP.NET Core中创建中间件的几种方式

前言 今天我们一起来盘点一下在ASP.NET Core应用程序中添加和创建中间件常见的四种方式。 中间件介绍 ASP.NET Core中间件(Middleware)是用于处理HTTP请求和响应的组件,它们被安排在请求处理管道中,并按顺序执行。中间件的设计是为了使其在请求处理管道中能够以灵活和可扩展的

推荐十个优秀的ASP.NET Core第三方中间件,你用过几个?

ASP.NET Core 作为一个强大的、跨平台的、高性能的开源框架,为开发者提供了丰富的功能和灵活的扩展性。其中,中间件(Middleware)是 ASP.NET Core 架构中的核心组件之一,它负责处理 HTTP 请求和响应的管道,允许开发者在请求和响应之间插入自定义逻辑。随着 ASP.NET

Asp-Net-Core开发笔记:使用原生的接口限流功能

前言 之前介绍过使用 AspNetCoreRateLimit 组件来实现接口限流 从 .Net7 开始,AspNetCore 开始内置限流组件,当时我们的项目还在 .Net6 所以只能用第三方的 现在都升级到 .Net8 了,当然是得来试试这个原生组件 体验后:配置使用都比较简单,不过功能也没有 A

ASP.NET Core如何禁用模型验证(或者从模型状态中移除某些属性)?

这是一篇4年前的文章:【经验分享】在ASP.NET Core中,如果禁用某个请求的模型验证? 事隔多年,又有网友问到这个问题。我就来重新整理一下,顺便扩展一下之前的解决办法。 这是一个来自网友【David】的提问。在 AppBoxCore 项目的新增用户页面,新增一个上传按钮: