解读ASP.NET 5 & MVC6系列教程(13):TagHelper_自学过程

在新版的MVC6中,微软提供了强大的TagHelper功能,以便让我们摆脱如下的臃肿代码:

@Html.LabelFor(model => model.FullName)
@Html.EditFor(model => model.FullName)
@Html.ValidationMessageFor(model => model.FullName)

引入新功能TagHelper以后,我们只需要这样定义就可以了,代码如下:

@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers" /* 这里需要首先引用TagHelper所在的命名空间 */

<label asp-for="FullName" class="control-label col-md-2"></label>
<div class="col-md-10">
 <input asp-for="FullName" class="form-control" />
 <span asp-validation-for="FullName"></span>
</div>

这种方式,抛去了服务器端代码,利用自定义html属性显得更加有语义,前端人员开起来也很舒服,极大地提高了前端开发人员的效率。

在默认的TagHelper实现里,不同的元素支持不同的自定义属性,以实现不同的用途,例如大部分元素都支持asp-for,而a元素则支持asp-controllerasp-action等,input元素最强大的,支持各种类型的type以及相关的格式。详细实现,请参考如下章节中的表格内容。

A元素

属性 描述
asp-controller Controller的名称
asp-action Action的名称
asp-host 网站的Host
asp-fragment URL的fragment名称
asp-protocol 网站协议(http或https)
asp-route Route名称
asp-route-
href 默认属性,如果href有值,则其它属性都不能设置任何值。

Form元素

属性 描述
asp-controller Controller的名称
asp-action Action的名称
asp-anti-forgery
asp-route-
action 默认属性,如果action有值,则其它属性都不能设置任何值。

Input元素

属性 描述
asp-for 模型字段的名称
asp-format 设置Type格式,具体如下:
格式 标准类型
HiddenInput hidden
Password password
Text text
PhoneNumber tel
Url url
EmailAddress email
Date date
DateTime datetime
DateTime-local datetime-local
Time time
Byte/SByte/Int16/UInt16/Int32/UInt32/Int64/UInt64/Single/Double number
Boolean checkbox
Decimal text
String text
IFormFile file
IEnumerable`IFormFile file

其中关于时间的具体格式如下:

属性 描述
date {0:yyyy-MM-dd}
datetime {0:yyyy-MM-ddTHH:mm:ss.fffK}
datetime-local {0:yyyy-MM-ddTHH:mm:ss.fff}
time {0:HH:mm:ss.fff}

Label元素

属性 描述
asp-for 模型字段的名称

textarea元素

属性 描述
asp-for 模型字段的名称

span元素

属性 描述
asp-validation-for 模型字段的名称

div元素

属性 描述
asp-validation-aummary ValidationSummary枚举值:
ValidationSummary.All
ValidationSummary.ModelOnly
ValidationSummary.None。

验证描述类型,只有选择了ValidationSummary.All和ValidationSummary.ModelOnly才能渲染该div元素。

select元素

属性 描述
asp-for 模型字段名称
asp-items 模型字段名称

link元素

属性 描述
asp-href-include
asp-href-exclude
asp-fallback-href 默认href加载失败时的备用地址
asp-fallback-href-include
asp-fallback-href-exclude
asp-fallback-test-class 判断加载失败时用到的class样式
asp-fallback-test-property 判断加载失败时用到的class样式中的属性
asp-fallback-test-value 判断加载失败时用到的class样式中的属性对应的值
asp-file-version
href 默认加载的css文件地址。

link的使用示例如下,比如我们定义如下代码:

<link rel="stylesheet"
href="//ajax.aspnetcdn.com/ajax/bootstrap-touch-carousel/0.8.0/css/bootstrap-touch-carousel.css"
asp-fallback-href="~/lib/bootstrap-touch-carousel/css/bootstrap-touch-carousel.css"
asp-fallback-test-class="carousel-caption"
asp-fallback-test-property="display"
asp-fallback-test-value="none" />

则该段代码表示,默认先加载aspnetcdn.com上的css文件,如果加载失败了,再加载本地网站里的css文件,加载失败的判断条件是:检测carousel-caption样式十分应用上了,即该应用了该样式的元素的display属性是否等于none。运行网站后,这段代码的生成html如下:

<link rel="stylesheet" href="//ajax.aspnetcdn.com/ajax/bootstrap-touch-carousel/0.8.0/css/bootstrap-touch-carousel.css" />
<meta name="x-stylesheet-fallback-test" class="carousel-caption" />
<script>
 !function (a, b, c) {
  var d, e = document,
   f = e.getElementsByTagName("SCRIPT"),
   g = f[f.length - 1].previousElementSibling,
   h = e.defaultView && e.defaultView.getComputedStyle ? e.defaultView.getComputedStyle(g) : g.currentStyle;

  if (h && h[a] !== b) {
   for (d = 0; d < c.length; d++) {
    e.write('<link rel="stylesheet" href="' + c[d] + '"/>')
   }
  }
 }("display", "none", ["\/lib\/bootstrap-touch-carousel\/css\/bootstrap-touch-carousel.css"]);
</script>

从中,我们看到,生成的HTML代码在link元素之后多了两个元素,一个是带有class="carousel-caption"属性的meta元素,一个是script脚本标签。其主要原理是如下:

在meta元素上应用定义的carousel-caption样式。通过JS代码检测该meta元素的display属性是否等于none。如果不等于none,重新加载本地的备用css文件。

注意,这里的js脚本是利用document.getElementsByTagName("SCRIPT"),获取最后一个SCRIPT标签的上一个兄弟元素的形式,来获取meta元素的。

script元素

属性 描述
asp-src-include
asp-src-exclude
asp-fallback-src 备用js文件地址
asp-fallback-src-include
asp-fallback-src-exclude
asp-fallback-test 判断默认js文件是否加载成功用到的对象
asp-file-version
src 默认的js文件地址。

script标签元素的fallback功能,和link元素记载css文件类型,只不过这里判断的不是class样式,而是检测某个对象是否存在,来判断默认的js文件是否加载成功,示例如下:

<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-1.10.2.min.js"
 asp-fallback-src="~/lib/jquery/jquery.min.js"
 asp-fallback-test="window.jQuery">
</script>

生成后的HTML代码,相对比较简单,示例如下:

<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-1.10.2.min.js">
</script>
<script>(window.jQuery||document.write("<script src=\"\/lib\/jquery\/jquery.min.js\"><\/script>"));</script>

多生成了一个script标签元素,然后判断jQuery对象是否存在,如果不存在则表示加载失败,那就再加载本地的备用js文件。

Cache

属性 描述
vary-by
vary-by-header
vary-by-query
vary-by-route
vary-by-cookie
vary-by-user
expires-on
expires-after
expires-sliding
priority
enabled .

利用EnvironmentTagHelper来控制不同运行环境的输出结果

在很多情况下,我们想再开发环境使用一套配置信息,在生产环境又是另外一套,这时候就需要使用条件判断语句了,不过在新版的MVC中,使用EnvironmentTagHelper提供的Environment元素标签就可以了,示例如下:

<environment names="Development">
 <script src="~/lib/jquery/jquery.js"></script>
 <script src="~/lib/bootstrap/js/bootstrap.js"></script>
 <script src="~/lib/hammer.js/hammer.js"></script>
 <script src="~/lib/bootstrap-touch-carousel/js/bootstrap-touch-carousel.js"></script>
</environment>
<environment names="Staging,Production">
 <script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-1.10.2.min.js"
   asp-fallback-src="~/lib/jquery/jquery.min.js"
   asp-fallback-test="window.jQuery">
 </script>
 <script src="//ajax.aspnetcdn.com/ajax/bootstrap/3.0.0/bootstrap.min.js"
   asp-fallback-src="~/lib/bootstrap/js/bootstrap.min.js"
   asp-fallback-test="window.jQuery">
 </script>
 <script src="//ajax.aspnetcdn.com/ajax/hammer.js/2.0.4/hammer.min.js"
   asp-fallback-src="~/lib/hammer.js/hammer.js"
   asp-fallback-test="window.Hammer">
 </script>
 <script src="//ajax.aspnetcdn.com/ajax/bootstrap-touch-carousel/0.8.0/js/bootstrap-touch-carousel.js"
   asp-fallback-src="~/lib/bootstrap-touch-carousel/js/bootstrap-touch-carousel.js"
   asp-fallback-test="window.Zepto">
 </script>
</environment>

在上述代码中,我们定于,如果是Development环境就使用本地的js文件,否则(Staging或Production环境)就先加载cdn的文件(只不过还留有备用方案)。

该names里的值判断依据是,查找IHostingEnvironmentEnvironmentName属性,并与其进行比较,然后再进行相应的处理。

自定义TagHelper

MVC所有TagHelper的实现,都继承了Microsoft.AspNet.Razor.Runtime.TagHelpers.ITagHelper接口,所以我们只要实现该接口就可以实现自定义的TagHelper,该接口的定义如下:

public interface ITagHelper
{
 int Order { get; }
 Task ProcessAsync(TagHelperContext context, TagHelperOutput output);
}

不过,我们一般自定义的时候,只需要继承该接口的默认实现TagHelper类,并重载其虚方法Process方法即可,如下是几个示例,我们来详细研究一下。

1. 在a元素上直接支持controller和action属性

public class ATagHelper : TagHelper
{
 [Activate]
 public IUrlHelper UrlHelper { get; set; }

 public string Controller { get; set; }

 public string Action { get; set; }

 public override void Process(TagHelperContext context, TagHelperOutput output)
 {
  if (Controller != null && Action != null)
  {
   var methodParameters = output.Attributes.ToDictionary(attribute => attribute.Key,
                 attribute => (object)attribute.Value);

   // 删除所有的attributes,因为路由里已经可以自动生成了
   output.Attributes.Clear();

   output.Attributes["href"] = UrlHelper.Action(Action, Controller, methodParameters);

   output.PreContent.SetContent("My ");
  }
 }
}

2. 自动识别Text文本中的链接,并提取出来

[TargetElement("p")]
public class AutoLinkerTagHelper : TagHelper
{
 public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
 {
  var childContent = await context.GetChildContentAsync();

  // Find Urls in the content and replace them with their anchor tag equivalent.
  output.Content.SetContent(Regex.Replace(
   childContent.GetContent(),
   @"\b(?:https?://|www\.)(\S+)\b",
   "<strong><a target=\"_blank\" href=\"http://$0\">$0</a></strong>"));
 }
}

3. 条件判断

定义一个condiction,符合条件才显示该元素,示例如下(只有Model.Approved为true时才显示该元素):

<p condition="Model.Approved" > @Model.CopyrightYear - My ASP.NET Application</p>

实现代码如下:

[TargetElement("div")]
[TargetElement("style")]
[TargetElement("p")]
public class ConditionTagHelper : TagHelper
{
 public bool? Condition { get; set; }

 public override void Process(TagHelperContext context, TagHelperOutput output)
 {
  // 如果设置了condition,并且该值为false,则不渲染该元素
  if (Condition.HasValue && !Condition.Value)
  {
   output.SuppressOutput();
  }
 }
}

4. 自定义元素的TagHelper

如果我们要为自定义元素定义TagHelper,则我们要符合约定规范,示例代码如下:

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属性赋值一个强类型的值,示例如下:

<website-information info="new WebsiteContext {
        Version = new Version(1, 1),
        CopyrightYear = 1990,
        Approved = true,
        TagsToShow = 30 }"/>

其渲染结果,则是渲染成一个包含4个p元素的section元素。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索5
, asp.net
, mvc6
TagHelper
,以便于您获取更多的相关知识。

时间: 2024-09-24 02:48:11

解读ASP.NET 5 & MVC6系列教程(13):TagHelper_自学过程的相关文章

解读ASP.NET 5 &amp; MVC6系列教程(12):基于Lamda表达式的强类型Routing实现_自学过程

前面的深入理解Routing章节,我们讲到了在MVC中,除了使用默认的ASP.NET 5的路由注册方式,还可以使用基于Attribute的特性(Route和HttpXXX系列方法)来定义.本章,我们将讲述一种基于Lambda表达式的强类型类型. 这种方式的基本使用示例如下: services.Configure<MvcOptions>(opt => { opt.EnableTypedRouting(); opt.GetRoute("homepage", c =>

解读ASP.NET 5 &amp; MVC6系列教程(1):ASP.NET 5简介_自学过程

ASP.NET 5简介 ASP.NET 5是一个跨时代的改写,所有的功能和模块都进行了独立拆分,做到了彻底解耦.为了这些改写,微软也是蛮 拼的,几乎把.NET Framwrok全部改写了一遍,形成了一个.NET Core的东西. 在.NET Core里一切都是可配置的,包括Session.MVC等功能,而一切可配置的功能都是可以在Nuget上进行下载. 目前ASP.NET 5依旧兼容老的.NET Framwrok,但要在进行跨平台的部署,还是只能使用新改版的.NET Core CLR. 目前的A

解读ASP.NET 5 &amp; MVC6系列教程(15):MvcOptions配置_自学过程

程序模型处理 IApplicationModelConvention 在MvcOptions的实例对象上,有一个ApplicationModelConventions属性(类型是:List<IApplicationModelConvention>),该属性IApplicationModelConvention类型的接口集合,用于处理应用模型ApplicationModel,该集合是在MVC程序启动的时候进行调用,所以在调用之前,我们可以对其进行修改或更新,比如,我们可以针对所有的Control

解读ASP.NET 5 &amp; MVC6系列教程(6):Middleware详解_自学过程

在第1章项目结构分析中,我们提到Startup.cs作为整个程序的入口点,等同于传统的Global.asax文件,即:用于初始化系统级的信息(例如,MVC中的路由配置).本章我们就来一一分析,在这里如何初始化这些系统级的信息. 新旧版本之间的Pipeline区别 ASP.NET 5和之前版本的最大区别是对HTTP Pipeline的全新重写,在之前的版本中,请求过滤器的通常是以HttpModule为模块组件,这些组件针对HttpApplication里定义的各个周期内的事件进行响应,从而用于实现

解读ASP.NET 5 &amp; MVC6系列教程(11):Routing路由_自学过程

新版Routing功能介绍 在ASP.NET 5和MVC6中,Routing功能被全部重写了,虽然用法有些类似,但和之前的Routing原理完全不太一样了,该Routing框架不仅可以支持MVC和Web API,还支持一般的ASP.NET5程序.新版的改变有如下几个部分. 首先,Routing系统是基于ASP.NET 5的,是一个独立于MVC的路由框架,而不是基于MVC的.MVC只是在上面扩展了一个快捷方式而已. 其次,在ASP.NET 5中,MVC和Web API控制器没有区别了,即合二为一了

解读ASP.NET 5 &amp; MVC6系列教程(3):项目发布与部署_自学过程

本章我们将讲解ASP.NET5项目发布部署相关的内容,示例项目以我们前一章创建的BookStore项目为例. 发布前的设置 由于新版ASP.NET5支持多版本DNX运行环境的发布和部署,所以在部署之前,我们需要设定部署的目标DNX(即之前的KRE). 步骤:右键BookStore项目->属性->Application选项卡,选择DNX的版本,本例中,选择dnx-coreclr-win-x64.1.0.0-beta4. 在project.json文件的commands节点,我们可以看到,系统默认

解读ASP.NET 5 &amp; MVC6系列教程(2):初识项目_自学过程

初识项目 打开VS2015,创建Web项目,选择ASP.NET Web Application,在弹出的窗口里选择ASP.NET 5 Website模板创建项目,图示如下: 我们可以看到,此时Web Forms\MVC\Web API复选框都选择不了,原有是因为在ASP.NET 5中做了大量更改,移除了Web Forms功能,将MVC.Web API.Web Pages这些功能合在了一起,所以自然就不需要这些复选框了.另外由于是CTP版,所以目前还没有提供单元测试项目的创建. 新创建的项目在VS

解读ASP.NET 5 &amp; MVC6系列教程(10):Controller与Action_自学过程

我们知道在MVC5和之前的版本,两个框架的生命周期是不一样的,在新版MVC6中,MVC Controller/Web API Controller已经合二为一了,本章我们主要讲解Controller和Action的定义与使用,以及在MVC框架中,如何根据路由查询相应的Controller和Action. Controller&Action的定义和使用 在新版MVC6框架中,依然提供了一个Controller基类,在这里除了依然提供了Url.RouteData.HttpContext.Reques

解读ASP.NET 5 &amp; MVC6系列教程(7):依赖注入_自学过程

在前面的章节(Middleware章节)中,我们提到了依赖注入功能(Dependency Injection),ASP.NET 5正式将依赖注入进行了全功能的实现,以便开发人员能够开发更具弹性的组件程序,MVC6也利用了依赖注入的功能重新对Controller和View的服务注入功能进行了重新设计:未来的依赖注入功能还可能提供更多的API,所有如果还没有开始接触依赖注入的话,就得好好学一下了. 在之前版本的依赖注入功能里,依赖注入的入口有MVC中的IControllerFactory和Web A