【ASP.NET Core】标记帮助器——替换元素名称
标记帮助器不仅可以给目标元素(标记)插入(或修改)属性,插入自定义的HTML内容,在某些需求中还可以替换原来标记的名称。
比如我们在使用 Blazor 时很熟悉的 Component 标记帮助器。在 Razor 文档中你将使用 <Component> 元素来设置要呈现的组件。而在实际处理时,会去掉 <Component> 元素,并呈现组件的HTML内容。
下面咱们举两个例子。
第一个比较简单,自定义的元素是 <textBox>,生成的元素是 <input type=text />。
[HtmlTargetElement("textBox", TagStructure = TagStructure.WithoutEndTag)]
public class TextInputTagHelper : TagHelper
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
// 将标记名称改为 input
output.TagName = "input";
// 设置 type 属性
output.Attributes.SetAttribute("type", "text");
}
}
这个不难理解,首先我们用的是候,在 Razor 文档使用的是元素是 <textbox>,而最后呈现出来的 HTML 是 <input> 元素。咱们就把它弄得像个控件那样用,是不是有点以前 ASP.NET 的味儿了?以前是有个前缀 asp:TextBox。
TagStructure.WithoutEndTag 的意思是指定这个标记没有结束标签,就像 <input > 或 <input />。
Razor 文档中要用 @addTagHelper 指令导入一下。
@addTagHelper *, TestApp
TestApp 是我这个程序集的名称,它导入此程序集下所有标记帮助器。
用起来也方便。
<div>
<TextBox />
</div>
运行之后,生成这样的 HTML。
<input type="text">
咱们确实可以让它更像传统 ASP.NET。
@addTagHelper *, TestApp
@tagHelperPrefix "asp:" <div>
<asp:textBox />
</div>
@tagHelperPrefix 就是为标记添加一个前缀,这里指定的是“asp:”,所以用的时候就真的捡到“童年回忆”了。想当年,ASP.NET 就是这么用的。
下面再举一例,咱们做 RadioButton(单选按钮)。选项之间互斥,同一个分组中你只能选择一项。在 HTML 中是 <input type=radio >,它没有“分组”属性,而是通过 name 属性来分组。name 相同的就是同一组,互斥。
注意的是,<input type=radio> 只显示个圈圈让你可以选中,可不包含选项文本。一般我们会给它配个 <label> 元素。然后,<label> 元素的 for 属性指向 <input> 的 id 属性。这样二者就关联了,点击<label>也能选中单选按钮。
所以,咱们实现的帮助器要生成一个<div>,里面包含<input>和<label>两个元素。
[HtmlTargetElement("radioButton", TagStructure = TagStructure.WithoutEndTag)]
public class RadioInputTagHelper : TagHelper {
// 分组名称
[HtmlAttributeName("group-name")]
public string? Group { get; set; } = "radio";
// id 值
public string? Id { get; set; } = string.Empty;
// 标签文本
public string? Label { get; set; }
// 默认是否选中
public bool IsChecked { get; set; } = false;
// 选项代表的值
public string? Value { get; set; } = string.Empty;
public override void Process(TagHelperContext context, TagHelperOutput output)
{
// 修改标记名称
output.TagName = null;
StringBuilder builder = new();
string html = $"""
<div>
<input type="radio" id="{Id}" name="{Group}" value="{Value}" {(IsChecked ? "checked" : "")} />
<label for="{Id}">{Label}</label>
</div>
""";
// 设置HTML内容
output.Content.SetHtmlContent(html);
}
}
默认情况下,在 Razor 文档中使用标记帮助器时,属性与.NET类属性相同。比如这个类中的 Label 属性,在Razor代码中也是Label属性。
<radioButton Label="老司机" ……>
如果你希望 HTML 属性与 .NET 属性不同,可以加上 [HtmlAttributeName] 特性,配分一个别名。
[HtmlAttributeName("group-name")]
咱们这个例子中,就为 Group 属性分配一个别名—— group-name。
<label> 元素只是呈现在HTML中的文本,让用户看,很多时候程序处理的往往不是这个,而是让标签对应一个值,即 Value 属性。Value 属性指定的值才是给程序用的。
我们来用一下这个单选按钮。
<div>
<radioButton group-name="abc" id="itme1" value="1" label="山药" is-checked="true" />
<radioButton group-name="abc" id="item2" value="2" label="鸭梨" />
<radioButton group-name="abc" id="item3" value="3" label="龙眼" />
<hr />
<radioButton group-name="good" id="item5" value="5" label="大卡车" />
<radioButton group-name="good" id="item6" value="6" label="皮卡" is-checked="true" />
<radioButton group-name="good" id="item4" value="4" label="独轮车" />
</div>
同一 group-name 下的选项是互斥关系,而不同组之间是互不影响的。
运行后,生成以下 HTML:
<div>
<input type="radio" id="itme1" name="abc" value="1" checked />
<label for="itme1">山药</label>
</div>
<div>
<input type="radio" id="item2" name="abc" value="2" />
<label for="item2">鸭梨</label>
</div>
<div>
<input type="radio" id="item3" name="abc" value="3" />
<label for="item3">龙眼</label>
</div>
<hr />
<div>
<input type="radio" id="item5" name="good" value="5" />
<label for="item5">大卡车</label>
</div>
<div>
<input type="radio" id="item6" name="good" value="6" checked />
<label for="item6">皮卡</label>
</div>
<div>
<input type="radio" id="item4" name="good" value="4" />
<label for="item4">独轮车</label>
</div>
</div>
结果如下图所示。

接下来看第三个例子。咱们来画一个圆,标记帮助器定义一个 <circle> 元素,我们直接设置相关属性就行。比如画布宽度、画布高度、圆的圆心、半径、线的粗细。然后会生成 <canvas> 元素和相关的 js 脚本代码。
[HtmlTargetElement("Circle")]
public class CircleTagHelper : TagHelper
{
// 圆的半径
public int Radius { get; set; }
// 线宽度
public int LineWidth { get; set; }
// 圆心-X
public int CenterX { get; set; }
// 圆心-Y
public int CenterY { get; set; }
// 画布宽度
public int Width { get; set; } = 300;
// 画布高度
public int Height { get; set; } = 300;
public override void Process(TagHelperContext context, TagHelperOutput output)
{
// 无标记名称
output.TagName = null;
// 生成的内容
string s = $"""
<canvas id="cv" width="{Width}" height="{Height}"></canvas>
<script>
var canvas = document.getElementById('cv');
var ctx = canvas.getContext('2d');
ctx.lineWidth = {LineWidth};
ctx.strokeStyle = 'blue';
ctx.beginPath();
ctx.arc({CenterX}, {CenterY}, {Radius}, 0, 2 * Math.PI);
ctx.stroke();
</script>
""";
output.Content.SetHtmlContent(s);
}
}
TagName 设置为 null 表示咱们这个帮助器不生产标签,而是用输出字符串 s 中那段代码。即这段代码直接呈现在 HTML 文档中,外部不用其他元素包装。
来,咱们在 Razor 文档中试试看。
<Circle center-x="115" center-y="90"
width="900"
height="900"
line-width="4"
radius="70" />
绘制的圆如下图所示。

生成的 HTML 如下:
<canvas id="cv" width="900" height="900"></canvas> <script>
var canvas = document.getElementById('cv');
var ctx = canvas.getContext('2d');
ctx.lineWidth = 4;
ctx.strokeStyle = 'blue';
ctx.beginPath();
ctx.arc(115, 90, 70, 0, 2 * Math.PI);
ctx.stroke();
</script>
用这个方法,咱们可以封装出许多图形绘制的标记,用的时候只要赋值一下属性即可,很省事的哟。
【ASP.NET Core】标记帮助器——替换元素名称的更多相关文章
- ASP.Net Core中使用jquery-ajax-unobtrusive替换Ajax.BeginForm
在大潮流下,大家都在研究MVVM框架,但是做面向搜索引擎的外网项目还是得用服务器渲染. 在.Net中肯定就是用Razor模板引擎了. .Net Core断臂式重构后,很多在老得Mvc中使用得好好的一些 ...
- ASP.NET Core Web 应用程序系列(三)- 在ASP.NET Core中使用Autofac替换自带DI进行构造函数和属性的批量依赖注入(MVC当中应用)
在上一章中主要和大家分享了在ASP.NET Core中如何使用Autofac替换自带DI进行构造函数的批量依赖注入,本章将和大家继续分享如何使之能够同时支持属性的批量依赖注入. 约定: 1.仓储层接口 ...
- ASP.NET Core Web 应用程序系列(二)- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)
在上一章中主要和大家分享在MVC当中如何使用ASP.NET Core内置的DI进行批量依赖注入,本章将继续和大家分享在ASP.NET Core中如何使用Autofac替换自带DI进行批量依赖注入. P ...
- ASP.NET Core利用拦截器 IActionFilter实现权限控制
“麦荻网教系统”采用了前后端代码分离的架构,即“Miidy.Cloud.Console”站与“Miidy.Cloud.Manage”站(两个前端站)同时通过web api的方式调用“Miidy.Clo ...
- 重学ASP.NET Core 中的标记帮助程序
标记帮助程序是什么 标记帮助程序使服务器端代码可以在 Razor 文件中参与创建和呈现 HTML 元素. 例如,内置的 ImageTagHelper 可以将版本号追加到图片名称. 每当图片发生变化时 ...
- 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 ...
- ASP.Net Core开发(踩坑)指南
ASP.NET与ASP.NET Core很类似,但它们之间存在一些细微区别以及ASP.NET Core中新增特性的使用方法,在此之前也写过一篇简单的对比文章ASP.NET MVC应用迁移到ASP.NE ...
- ASP.NET Core MVC 概述
https://docs.microsoft.com/zh-cn/aspnet/core/mvc/overview?view=aspnetcore-2.2 ASP.NET Core MVC 概述 20 ...
- 在Asp.NET Core中如何优雅的管理用户机密数据
在Asp.NET Core中如何优雅的管理用户机密数据 背景 回顾 在软件开发过程中,使用配置文件来管理某些对应用程序运行中需要使用的参数是常见的作法.在早期VB/VB.NET时代,经常使用.ini文 ...
- 用ASP.NET Core 2.1 建立规范的 REST API -- HATEOAS
本文所需的一些预备知识可以看这里: http://www.cnblogs.com/cgzl/p/9010978.html 和 http://www.cnblogs.com/cgzl/p/9019314 ...
随机推荐
- 【每日一题】【第n个 n-->0】19./NC53 【删除】链表的倒数第 N 个结点-211123/220127
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点. 答案: import java.util.*; /* * public class ListNode { * int val; * ...
- 01-复杂度2 Maximum Subsequence Sum (25分)
Sample Input: 10 -10 1 2 3 4 -5 -23 3 7 -21 Sample Output: 10 1 4 题目有一个测试点是"最大和前面有一段是0",所以 ...
- 前端HTML不使用flash兼容IE浏览器播放视频
前言:最近公司项目上有个需求就是在IE8上不使用flash技术来去实现视频播放 分析:IE8不支持HTML5,所以不能使用video标签,在非IE的浏览器可以使用video标签 目录 我的解决 DEM ...
- C#关于委托的一些事,开发日志
----- 委托是什么------ 其实委托事件很好理解,就当成是c语言中的函数指针或者是回调函数,或者说换种理解方式,信号和槽?触发器和接收器?总之就是一个地方调用了这个函数,那么在另一个地方也会调 ...
- Scrum敏捷开发方法实践
前言 作者所在的公司在项目开发的过程中采用着当下互联网公司中流行的小步快跑开发策略,特别借鉴了敏捷开发中的迭代递增思想来指导项目的开发.我们经过对相关敏捷开发方法的调查研究,最终采用了Scrum敏 ...
- java线程基础知识整理
目录 线程基本概念 1.java实现线程 2.线程的生命周期 3.线程常用的方法 3.1.sleep() 3.2.interrupt方法 3.3.stop方法 4.线程调度 4.1.常见的线程调度模型 ...
- 第七节 VOR/DME进近程序保护区的绘制
飞行程序设计软件实践 通过前面六节的练习,2023社区版插件的主要功能都已经使用到了.今天通过VOR/DME非精密进近程序,再将这些功能串起来使用一下.今天的软件,我们使用浩辰CAD2023版(过期后 ...
- 问一个 Windows 窗口的 Capture 问题
好久没写了,上来先问一个问题...羞射... 有 A.B 两个窗口,A 是 B 的 Owner,B 不激活不抢焦点.在 B 的 WM_LBUTTONDOWN 的时候,设置 A 窗口为 Capture: ...
- [cocos2d-x]从源码角度思考convertToWorldSpace()与convertToWorldSpaceAR()坐标系的转换
convertToWorldSpace() 话不多说,先上源码,之后再慢慢讲解: (5和6图截图的时候重复了,这里就不弄出来了) 只要通过图1到图8中我写的注释进行分析(不懂的地方可以自己去翻一下co ...
- A+B Problem C++
前言继上次发表的A+B Problem C语言后,今天我们来学习一下A+B Problem C++ 正文什么是C++? C++既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象 ...