当我们新建了一个.Net Core类型的Project时,我们会看到页面上有类似于这样的代码:

当我们运行项目,查看源代码会发现,浏览器中的就是Html代:

那么,为什么我们在页面写的代码会转化为html标签呢?接下来我们就来探索这个秘密。

当我们在vs中把鼠标放到这样的元素上时发现这样的元素都是一个Microsoft.AspNetCore.Mvc.TagHelpers命名空间下的对象,我们通过Reflector查看a标签的对象AnchorTagHelper

[HtmlTargetElement("a", Attributes="asp-action"), HtmlTargetElement("a", Attributes="asp-controller"), HtmlTargetElement("a", Attributes="asp-area"), 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
{
// Fields
private IDictionary<string, string> _routeValues;
private const string ActionAttributeName = "asp-action";
private const string AreaAttributeName = "asp-area";
private const string ControllerAttributeName = "asp-controller";
private const string FragmentAttributeName = "asp-fragment";
private const string HostAttributeName = "asp-host";
private const string Href = "href";
private const string ProtocolAttributeName = "asp-protocol";
private const string RouteAttributeName = "asp-route";
private const string RouteValuesDictionaryName = "asp-all-route-data";
private const string RouteValuesPrefix = "asp-route-"; // Methods
public AnchorTagHelper(IHtmlGenerator generator);
public override void Process(TagHelperContext context, TagHelperOutput output); // Properties
[HtmlAttributeName("asp-action")]
public string Action { get; set; }
[HtmlAttributeName("asp-area")]
public string Area { get; set; }
[HtmlAttributeName("asp-controller")]
public string Controller { get; set; }
[HtmlAttributeName("asp-fragment")]
public string Fragment { get; set; }
protected IHtmlGenerator Generator { [CompilerGenerated] get; }
[HtmlAttributeName("asp-host")]
public string Host { get; set; }
public override int Order { get; }
[HtmlAttributeName("asp-protocol")]
public string Protocol { get; set; }
[HtmlAttributeName("asp-route")]
public string Route { get; set; }
[HtmlAttributeName("asp-all-route-data", DictionaryAttributePrefix="asp-route-")]
public IDictionary<string, string> RouteValues { get; set; }
[HtmlAttributeNotBound, ViewContext]
public ViewContext ViewContext { get; set; }
}
首先,这个类继承自抽象类TagHelper
public abstract class TagHelper : ITagHelper
{
// Methods
protected TagHelper();
public virtual void Init(TagHelperContext context);
public virtual void Process(TagHelperContext context, TagHelperOutput output);
public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output); // Properties
public virtual int Order { [CompilerGenerated] get; }
}
TagHelper又继承自ITagHelper接口
public interface ITagHelper
{
// Methods
void Init(TagHelperContext context);
Task ProcessAsync(TagHelperContext context, TagHelperOutput output); // Properties
int Order { get; }
}
这个接口只有两个方法,Init和ProcessAsync,我们也许会猜到,转化的过程就是通过这两个方法来转化的。没错,你猜对了。
我们回到AnchorTagHelper类中,查看Process方法:
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (output == null)
{
throw new ArgumentNullException("output");
}
if (output.Attributes.ContainsName("href"))
{
if ((((this.Action != null) || (this.Controller != null)) || ((this.Area != null) || (this.Route != null))) || (((this.Protocol != null) || (this.Host != null)) || ((this.Fragment != null) || (this.RouteValues.Count != ))))
{
throw new InvalidOperationException(Resources.FormatAnchorTagHelper_CannotOverrideHref("<a>", "asp-action", "asp-controller", "asp-area", "asp-route", "asp-protocol", "asp-host", "asp-fragment", "asp-route-", "href"));
}
}
else
{
TagBuilder builder;
IDictionary<string, object> routeValues = null;
if ((this._routeValues != null) && (this._routeValues.Count > ))
{
routeValues = new Dictionary<string, object>(this._routeValues.Count, StringComparer.OrdinalIgnoreCase);
foreach (KeyValuePair<string, string> pair in this._routeValues)
{
routeValues.Add(pair.Key, pair.Value);
}
}
if (this.Area != null)
{
if (routeValues == null)
{
routeValues = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
}
routeValues["area"] = this.Area;
}
if (this.Route == null)
{
builder = this.Generator.GenerateActionLink(this.ViewContext, string.Empty, this.Action, this.Controller, this.Protocol, this.Host, this.Fragment, routeValues, null);
}
else
{
if ((this.Action != null) || (this.Controller != null))
{
throw new InvalidOperationException(Resources.FormatAnchorTagHelper_CannotDetermineHrefRouteActionOrControllerSpecified("<a>", "asp-route", "asp-action", "asp-controller", "href"));
}
builder = this.Generator.GenerateRouteLink(this.ViewContext, string.Empty, this.Route, this.Protocol, this.Host, this.Fragment, routeValues, null);
}
if (builder != null)
{
output.MergeAttributes(builder);
}
}
}
,发现这个方法主要就是根据我们填写的属性、ViewContext(View上下文)、routeValue(路由信息)来生成Html标签,主要方法就是在GenerateRouteLink生成一个TagBuilder类型的对象,再通过output.MergeAttributes(builder);生成TagHelperOutput类型的对象。
那么,我们在页面上写的属性是怎么与AnchorTagHelper中的属性关联的呢?
我们可以看这个类中的属性,每个属性前面都有一个[HtmlAttributeName("asp-action")] ,标记这个属性和我们页面上写的asp-**属性关联的。
综上,如果我们不清楚具体的某个TagHelper有哪些属性,我们可以通过反编译查看,当然没必要。我们只要通过VS直接通过智能感知系统就可以点出来这些属性。
 
我们还可以自定义自己的Tag,只要继承自ITagHelper,实现方法就可以
 
public class WebsiteInformationTagHelper : TagHelper
{
public WebsiteContext Info { get; set; } public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "section";
output.PostContent.SetContent(string.Format(
"<p><strong>Version:</strong> {0}</p>" + Environment.NewLine +
"<p><strong>Copyright Year:</strong> {1}</p>" + Environment.NewLine +
"<p><strong>Approved:</strong> {2}</p>" + Environment.NewLine +
"<p><strong>Number of tags to show:</strong> {3}</p>" + Environment.NewLine,
Info.Version.ToString(),
Info.CopyrightYear.ToString(),
Info.Approved.ToString(),
Info.TagsToShow.ToString()));
output.SelfClosing = false;
}
}
<website-information info="new WebsiteContext {
Version = new Version(1, 1),
CopyrightYear = 1990,
Approved = true,
TagsToShow = 30 }"/>
 
 
 
 

ASP.Net Core-TagHelpers的更多相关文章

  1. ASP.NET Core 中文文档 第四章 MVC(3.2)Razor 语法参考

    原文:Razor Syntax Reference 作者:Taylor Mullen.Rick Anderson 翻译:刘怡(AlexLEWIS) 校对:何镇汐 什么是 Razor? Razor 是一 ...

  2. ASP.NET Core 中文文档 第四章 MVC(3.3)布局视图

    原文:Layout 作者:Steve Smith 翻译:娄宇(Lyrics) 校对:孟帅洋(书缘) 视图(View)经常共享视觉元素和编程元素.在本篇文章中,你将学习如何在你的 ASP.NET 应用程 ...

  3. ASP.NET Core 中文文档 第四章 MVC(3.6.1 )Tag Helpers 介绍

    原文:Introduction to Tag Helpers 作者:Rick Anderson 翻译:刘浩杨 校对:高嵩(Jack) 什么是 Tag Helpers? Tag Helpers 提供了什 ...

  4. ASP.NET Core 中文文档 第四章 MVC(3.6.2 )自定义标签辅助类(Tag Helpers)

    原文:Authoring Tag Helpers 作者:Rick Anderson 翻译:张海龙(jiechen) 校对:许登洋(Seay) 示例代码查看与下载 从 Tag Helper 讲起 本篇教 ...

  5. Asp.Net Core 项目实战之权限管理系统(5) 用户登录

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  6. ASP.NET Core MVC TagHelper实践HighchartsNET快速图表控件-开源

    ASP.NET Core MVC TagHelper最佳实践HighchartsNET快速图表控件支持ASP.NET Core. 曾经在WebForms上写过 HighchartsNET快速图表控件- ...

  7. 【无私分享:ASP.NET CORE 项目实战(第九章)】创建区域Areas,添加TagHelper

    目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 在Asp.net Core VS2015中,我们发现还有很多不太简便的地方,比如右击添加视图,转到试图页等功能图不见了,虽然我 ...

  8. [asp.net core]定义Tag Helpers

    原文地址 https://docs.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/authoring Getting started wi ...

  9. [asp.net core] Tag Helpers 简介(转)

    原文地址 https://docs.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro What are Tag Helpers? ...

  10. ASP.NET Core 十种方式扩展你的 Views

    原文地址:http://asp.net-hacker.rocks/2016/02/18/extending-razor-views.html 作者:Jürgen Gutsch 翻译:杨晓东(Savor ...

随机推荐

  1. linux0.11文件分析

    在kernel包中有几个重要的文件夹和文件,他们各司其职,处理着有关内核的一些功能操作.其中文件夹有三个:blk_drv(块设备驱动),chr_drv(字符设备驱动),math(数学协处理器)  文件 ...

  2. GPS(1)核心API及3种列出LocationProvider的方法

    GPS的常用API Android SDK为GPS提供了很多API,其中LocationManager类是这些API的核心.所有与GPS相关的操作都由LocationManager对象及其派生的对象完 ...

  3. Rails中的MIME类型

    layout title date comments categories post rails的中的MIME类型 2014-09-08 21:40 true ruby Rails开发中经常使用不同的 ...

  4. ORACLE-修改当前会话的语言环境

    修改当前会话的语言环境变量参数:ALTER SESSION SET =将语言改为英语: SQL> ALTER SESSION SET NLS_LANGUAGE='AMERICAN';SESSIO ...

  5. poj 1416 Shredding Company( dfs )

    我的dfs真的好虚啊……,又是看的别人的博客做的 题目== 题目:http://poj.org/problem?id=1416 题意:给你两个数n,m;n表示最大数,m则是需要切割的数. 切割m,使得 ...

  6. 使用Unity3d的Physics.Raycast()的用法做子弹射击

    Class Functions 1)static function Raycast (origin : Vector3, direction : Vector3, distance : float = ...

  7. [NOI2005] 维修数列

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 8397  Solved: 2530 Description In ...

  8. TCP编程(七)

    此为网络编程的一个系列,后续会把内容补上...

  9. [VC6]ONMESSAGE()宏编译时出现"sytax error ;"错误时

    自定义消息时编译出错,经排查,在定义消息的头文件里 #define WM_XXX (WM_USER+1000); 最后多加了一个分号引起. 吐血.

  10. 【转】Android动态改变对 onCreateDialog话框值 -- 不错不错!!!

    原文网址:http://www.111cn.net/sj/android/46484.htm 使用方法是这样的,Activity.showDialog()激发Activity.onCreateDial ...