ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

《 Pro ASP.NET Core 6 》--- 读书随记(8)

2022-07-03 10:35:50  阅读:201  来源: 互联网

标签:Core ASP Helper 元素 应用程序 Tag 随记 public 属性


Part 3

CHAPTER 25

内容来自书籍:

Pro ASP.NET Core 6
Develop Cloud-Ready Web Applications Using MVC, Blazor, and Razor Pages (Ninth Edition)

Author: Adam Freeman
需要该电子书的小伙伴,可以留下邮箱,有空看到就会发送的

Using Tag Helpers

Tag helpers 是在视图或页面中转换 HTML 元素的 C # 类。Tag helpers 的常见用途包括使用应用程序的路由配置为表单生成 URL,确保特定类型的元素样式一致,以及用常用的内容片段替换自定义简写元素。

Creating a Tag Helper

我通过创建和应用一个 Tag Helper 来设置 tr 元素的 Bootstrap CSS 类

<tr tr-color="primary">
    <th colspan="2">Product Summary</th>
</tr>

转换为:

<tr class="bg-primary text-white text-center">
    <th colspan="2">Product Summary</th>
</tr>

Defining the Tag Helper Class

Tag helpers 可以在项目的任何地方定义,但是将它们放在一起会有所帮助,因为它们需要注册才能使用

namespace WebApp.TagHelpers {
    public class TrTagHelper: TagHelper {
        public string BgColor { get; set; } = "dark";
        public string TextColor { get; set; } = "white";
        public override void Process(TagHelperContext context,
                TagHelperOutput output) {
            output.Attributes.SetAttribute("class",
                $"bg-{BgColor} text-center text-{TextColor}");
        }
    }
}
Receiving Context Data

Tag helpers 通过 TagHelperContext 类的实例接收有关它们正在转换的元素的信息

虽然您可以通过 AllAttributesdictionary 访问元素属性的详细信息,但是更方便的方法是定义一个名称与您感兴趣的属性相对应的属性

属性的名称会自动从默认的 HTML 样式 bg-color 转换为 C # 样式 BgColor。您可以使用任何属性前缀,除了 asp- (Microsoft 使用的)和 data-(为发送到客户端的自定义属性保留的)。示例 Tag Helper 将使用 bg-color 和 text-color 属性进行配置,这些属性将为 BgColor 和 textColor 属性提供值,并用于在 Process 方法中配置 tr 元素,如下所示:

Producing Output

Process 方法通过配置作为参数接收的 TagHelperOutput 对象来转换元素。TagHelperOut 对象首先描述出现在视图中的 HTML 元素,然后通过下图描述的属性和方法进行修改。

Registering Tag Helpers

Tag Helper 类在使用之前必须使用@addTagHelper 指令进行注册

如果想要在所有的地方都可以使用Tag Hepler,可以在_ViewImports.cshtml 全局导入

@addTagHelper *, WebApp

第一个参数的含义是指定tag Helper 的类名并且支持通配符,第二部分是指定这个类是在哪个程序集(assembly)定义的

Using a Tag Helper

<tr bg-color="info" text-color="white">

清单25-7中应用属性的 tr 元素已经被转换,但这不是图中显示的唯一更改。默认情况下,Tag helpers 应用于特定类型的所有元素,这意味着视图中的所有 tr 元素已经使用在 Tag Helper 类中定义的默认值进行了转换,因为没有定义任何属性。(有些表行不显示文本的原因是 Bootstrap table-striped类,它将不同的样式应用于替换行。)

事实上,问题更为严重,因为视图导入文件中的@addTagHelper 指令意味着示例 Tag Helper 应用于控制器和 Razor 页面呈现的任何视图中使用的所有 tr 元素。

Narrowing the Scope of a Tag Helper

可以使用 HtmlTargetElement 元素控制由 Tag Helper 转换的元素范围

namespace WebApp.TagHelpers {
    [HtmlTargetElement("tr", Attributes = "bg-color,text-color", ParentTag = "thead")]
    public class TrTagHelper : TagHelper {
        public string BgColor { get; set; } = "dark";
        public string TextColor { get; set; } = "white";
        public override void Process(TagHelperContext context,
                TagHelperOutput output) {
            output.Attributes.SetAttribute("class",
                $"bg-{BgColor} text-center text-{TextColor}");
        }
    }
}

Attritribute 属性支持 CSS 属性选择器语法,所以[ bg-color ]匹配具有 bg-color 属性的元素,[ bg-color = primary ]匹配具有 bg-color 属性的元素,该属性的值是primary,并且[ bg-color^=p ]匹配具有 bg-color 属性的元素,该属性的值以 p 开头。上文中 Tag Helper 的属性与 tr 元素匹配,它们同时具有 bg-color 和 text-color 属性,这两个属性都是 head 元素的子元素。

Widening the Scope of a Tag Helper

HtmlTargetElement 属性还可以用来扩展 Tag Helper 的范围,使其匹配范围更广的元素。这是通过将属性的第一个参数设置为星号(* 字符)来完成的,该星号匹配任何元素

[HtmlTargetElement("*", Attributes = "bg-color,text-color")]

如果担心匹配的范围过大,这个属性可以叠加使用

[HtmlTargetElement("tr", Attributes = "bg-color,text-color")]
[HtmlTargetElement("td", Attributes = "bg-color")]

如果想对同一个元素应用不同的tag,可以设置tag之间的顺序,Order属性是继承自TagHelper,用来决定tag的执行顺序

Advanced Tag Helper Features

Creating Shorthand Elements

Tag helpers 并不局限于转换标准的 HTML 元素,亦可以用常用的内容取代自订元素。这对于使视图更加简洁和使其意图更加明显是一个有用的特性

<tablehead bg-color="dark">Product Summary</tablehead>

这个自定义标签是不会被浏览器识别的,所以我们会创建一个Tag Helper来生成具体的标准的HTML元素

namespace WebApp.TagHelpers {

    [HtmlTargetElement("tablehead")]
    public class TableHeadTagHelper: TagHelper {

    public string BgColor { get; set; } = "light";
        public override async Task ProcessAsync(TagHelperContext context,
                TagHelperOutput output) {
            output.TagName = "thead";
            output.TagMode = TagMode.StartTagAndEndTag;
            output.Attributes.SetAttribute("class",
                $"bg-{BgColor} text-white text-center");
            string content = (await output.GetChildContentAsync()).GetContent();
            output.Content
                .SetHtmlContent($"<tr><th colspan=\"2\">{content}</th></tr>");
        }
    }
}

然后上面的标签会变成:

<thead class="bg-dark text-white text-center">
    <tr>
        <th colspan="2">Product Summary</th>
    </tr>
</thead>

Creating Elements Programmatically

我们使用标准的c#中的string格式来创建我们需要的内容,但是这不安全,因为很可能会打错字。

一个更安全有效的方法是使用 TagBuilder 类,允许以更结构化的方式创建元素

            TagBuilder header = new TagBuilder("th");
            header.Attributes["colspan"] = "2";
            header.InnerHtml.Append(content);
            TagBuilder row = new TagBuilder("tr");
            row.InnerHtml.AppendHtml(header);
            output.Content.SetHtmlContent(row);

Prepending and Appending Content and Elements

TagHelperOutput 类提供了四个属性,可以很容易地将新内容注入到视图中,使其包围元素或元素的内容

Inserting Content Around the Output Element
namespace WebApp.TagHelpers {
    [HtmlTargetElement("*", Attributes = "[wrap=true]")]
    public class ContentWrapperTagHelper: TagHelper {
        public override void Process(TagHelperContext context,
                TagHelperOutput output) {
            TagBuilder elem = new TagBuilder("div");
            elem.Attributes["class"] = "bg-primary text-white p-2 m-2";
            elem.InnerHtml.AppendHtml("Wrapper");
            output.PreElement.AppendHtml(elem);
            output.PostElement.AppendHtml(elem);
        }
    }
}

使用<div class="m-2" wrap="true">Inner Content</div>

效果:

Inserting Content Inside the Output Element
namespace WebApp.TagHelpers {
    [HtmlTargetElement("*", Attributes = "[highlight=true]")]
    public class HighlightTagHelper: TagHelper {
        public override void Process(TagHelperContext context,
                TagHelperOutput output) {
            output.PreContent.SetHtmlContent("<b><i>");
            output.PostContent.SetHtmlContent("</i></b>");
        }
    }
}

使用<tr><th>Name</th><td highlight="true">@Model?.Name</td></tr>

Getting View Context Data

[ViewContext]
[HtmlAttributeNotBound]
public ViewContext Context { get; set; } = new();

ViewContext 属性表示,当创建Tag Helper对象类的新实例时,该属性的值应该被赋予一个 ViewContext,该实例提供正在呈现的视图的详细信息,包括路由数据

如果在 div 元素上定义了匹配的属性,则 HtmlAttributeNotBound 属性阻止将值分配给此属性。这是一个很好的实践,特别是当你正在为其他开发者写 Tag helpers 的时候。

Suppressing the Output Element

Tag helpers 可以通过调用作为 Process 方法参数接收的 TagHelperOutput 对象上的 SuppressOut 方法来防止元素包含在 HTML 响应中

<div show-when-gt="500" for="Price">
    <h5 class="bg-danger text-white text-center p-2">
        Warning: Expensive Item
    </h5>
</div>
namespace WebApp.TagHelpers {
    [HtmlTargetElement("div", Attributes = "show-when-gt, for")]
    public class SelectiveTagHelper : TagHelper {
        public decimal ShowWhenGt { get; set; }
        public ModelExpression? For { get; set; }
        public override void Process(TagHelperContext context,
                TagHelperOutput output) {
            if (For?.Model.GetType() == typeof(decimal)
                    && (decimal)For.Model <= ShowWhenGt) {
                output.SuppressOutput();
            }
        }
    }
}

Tag Helper 使用模型表达式访问属性,并调用 SuppressOutput 方法,除非超过阈值

CHAPTER 26

Using the Built-in Tag Helpers

Enabling the Built-in Tag Helpers

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Transforming Anchor Elements

A 元素是在应用程序周围导航并向应用程序发送 GET 请求的基本工具。AnchorTagHelper 类用于转换元素的 href 属性,这样它们可以针对使用路由系统生成的 URL,这意味着不需要硬编码的 URL,路由配置的变化将自动反映在应用程序的锚元素中

AnchorTagHelper 简单且可预测,使得在使用应用程序路由配置的元素中生成 URL 变得非常容易。

<td>
    <a asp-action="index" asp-controller="home" asp-route-id="@Model?.ProductId"
          class="btn btn-sm btn-info text-white">
            Select
    </a>
</td>

Asp-action 和 asp-controller 属性指定操作方法的名称和定义它的控制器。段变量的值是使用 asp-path-[ name ]属性定义的,例如 asp-path-id 属性为 id 段变量提供一个值,用于为 asp-action 属性选择的 action 方法提供一个参数。

上面最终返回的html是

<a class="btn btn-sm btn-info text-white" href="/Home/index/3">Select</a>

Using Anchor Elements for Razor Pages

Asp-Page 属性用于指定一个 Razor 页面作为锚元素 href 属性的目标。页面的路径以/字符为前缀,@page 指令定义的路由段的值使用 asp-path-[ name ]属性定义。

<a asp-page="/suppliers/list" class="btn btn-secondary">Suppliers</a>

Using the JavaScript and CSS Tag Helpers

ASP.NET Core 提供了一些 Tag helpers,用于通过 script 和 link 元素管理 JavaScript 文件和 CSS 样式表。这些 Tag helpers 强大而灵活,但需要密切关注,以避免产生意想不到的结果。

Managing JavaScript Files

ScriptTagHelper 类是 script 元素的内置 Tag Helper,用于管理/n包含 JavaScript 文件

Selecting JavaScript Files

Asp-src-include 属性用于在使用 globbing 模式的视图中包含 JavaScript 文件。Globbing 模式支持一组用于匹配文件的通配符

Globbing 是确保视图包含应用程序需要的 JavaScript 文件的一种有用方法,即使文件的确切路径发生了变化,这种情况通常发生在文件名中包含版本号或包添加额外文件时。

<script asp-src-include="lib/jquery/**/*.js"></script>

Managing CSS Stylesheets

Selecting Stylesheets

LinkTagHelper 与 ScriptTagHelper 共享许多特性,包括支持 globbing 模式来选择或排除 CSS 文件,这样就不必单独指定它们。能够准确地选择 CSS 文件和 JavaScript 文件一样重要,因为样式表可以有常规和缩小的版本,并且支持源地图

<link asp-href-include="/lib/bootstrap/css/*.min.css"
          asp-href-exclude="**/*-reboot*,**/*-grid*,**/*-utilities*, **/*.rtl.*"
          rel="stylesheet" />

Using the Data Cache

CacheTagHelper 类允许缓存内容片段,以加速视图或页面的呈现。要缓存的内容使用 cache 元素表示

<h6 class="bg-primary text-white m-2 p-2">
            Uncached timestamp: @DateTime.Now.ToLongTimeString()
</h6>
<cache>
    <h6 class="bg-primary text-white m-2 p-2">
        Cached timestamp: @DateTime.Now.ToLongTimeString()
    </h6>
</cache>

CacheTagHelper 类使用的缓存是基于内存的,这意味着它的容量受到可用 RAM 的限制,并且每个应用服务器维护一个单独的缓存。当可用容量不足时,内容将从缓存中弹出,当应用程序停止或重新启动时,整个内容将丢失。

Setting Cache Expiry

<cache expires-after="@TimeSpan.FromSeconds(15)">

Setting a Fixed Expiry Point

<cache expires-on="@DateTime.Parse("2100-01-01")">

我已经指定该数据应该缓存到2100年。这不是一个有用的缓存策略,因为应用程序很可能会在下个世纪开始之前重新启动,但它确实说明了如何在将来指定一个固定点,而不是表示相对于内容被缓存的时刻的到期点。

Setting a Last-Used Expiry Period

<cache expires-sliding="@TimeSpan.FromSeconds(10)">

expires-sliding属性用于指定内容没有从缓存中检索到的过期时间

如果在10秒内重新加载页面,将使用缓存的内容。如果等待重新加载页超过10秒,那么缓存的内容将被丢弃,视图组件将用于生成新内容,进程将重新开始。

Using Cache Variations

<cache expires-sliding="@TimeSpan.FromSeconds(10)" vary-by-route="action">

默认情况下,所有请求都接收相同的缓存内容。CacheTagHelper 类可以维护缓存内容的不同版本,并使用它们来满足不同类型的 HTTP 请求,这些请求是使用名称开头为 vary-by 的属性之一指定的

您将看到,每个窗口都会收到自己的缓存内容和自己的到期日期,因为每个请求都会产生不同的action路由值。

Using the Hosting Environment Tag Helper

Environment TagHelper 类应用于自定义环境元素,并根据宿主环境确定在发送到浏览器的 HTML 中是否包含内容区域

        <environment names="development">
            <h2 class="bg-info text-white m-2 p-2">This is Development</h2>
        </environment>
        <environment names="production">
            <h2 class="bg-danger text-white m-2 p-2">This is Production</h2>
        </environment>

CHAPTER 27

Using the Forms Tag Helpers

这章节描述了用于创建 HTML 表单的内置 Tag helpers。这些 Tag helpers 确保表单提交给正确的操作或页面处理程序方法,并且元素准确地表示特定的模型属性

Understanding the Form Handling Pattern

首先,浏览器发送一个 HTTP GET 请求,这将导致包含表单的 HTML 响应,从而使用户可以向应用程序提供数据。用户单击一个按钮,该按钮通过 HTTP POST 请求提交表单数据,这允许应用程序接收和处理用户的数据。处理完数据后,将发送响应,该响应将浏览器重定向到确认用户操作的 URL。

这就是所谓的 POST/Redirect/Get 模式,重定向非常重要,因为它意味着用户可以单击浏览器的重载按钮而无需发送另一个 POST 请求,这可能会导致无意中重复某个操作。

Creating a Controller to Handle Forms

        public async Task<IActionResult> Index(long id = 1) {
            return View("Form", await context.Products.FindAsync(id));
        }

        [HttpPost]
        public IActionResult SubmitForm() {
            foreach (string key in Request.Form.Keys
                    .Where(k => !k.StartsWith("_"))) {
                TempData[key] = string.Join(", ", Request.Form[key]);
            }
            return RedirectToAction(nameof(Results));
        }

        public IActionResult Results() {
            return View();
        }

Using Tag Helpers to Improve HTML Forms

上一节的例子展示了处理 HTML 表单的基本机制,但是 ASP.NET Core 包含了转换表单元素的 Tag helpers

Working with Form Elements

FormTagHelper 类是表单元素的内置 Tag Helper,用于管理 HTML 表单的配置,以便它们针对正确的操作或页面处理程序,而不需要对 URL 进行硬编码

<form asp-action="submitform" method="post">

<form asp-page="FormHandler" method="post">

Working with input Elements

Input 元素是 HTML 表单的骨干,为用户提供应用程序的主要非结构化数据。InputTagHelper 类用于转换输入元素,以便它们反映用于收集的视图模型属性的数据类型和格式

<input class="form-control" asp-for="Name" />

Applying Formatting via the Model Class

[DisplayFormat(DataFormatString = "{0:c2}", ApplyFormatInEditMode = true)]
public decimal Price { get; set; }

Working with label Elements

<label asp-for="ProductId"></label>

Working with Select and Option Elements

<select class="form-control" asp-for="CategoryId">
    <option value="1">Watersports</option>
    <option value="2">Soccer</option>
    <option value="3">Chess</option>
</select>
<select class="form-control" asp-for="CategoryId" asp-items="@ViewBag.Categories">
</select>

Working with Text Areas

Textarea 元素用于从用户那里获取大量的文本,通常用于非结构化数据,例如注释或观察。

<textarea class="form-control" asp-for="Supplier.Name"></textarea>

Using the Anti-forgery Feature

结果中显示的 _ RequestVerificationToken 表单值是 FormTagHelper 应用于防止跨站请求伪造的安全特性。跨站请求伪造(CSRF)利用用户请求通常被认证的方式来开发 web 应用程序。大多数 Web 应用程序ーー包括那些使用 ASP.NET Core 创建的应用程序ーー都使用 Cookie 来识别哪些请求与某个特定会话相关联,而用户标识通常与这些请求相关联。

CSRF ーー也称为 XSRF ーー依赖于用户在使用 Web 应用程序后访问恶意网站,而且没有明确结束会话。应用程序仍将用户的会话视为处于活动状态,并且浏览器存储的 Cookie 尚未过期。恶意站点包含 JavaScript 代码,该代码向应用程序发送表单请求,以便在未经用户同意的情况下执行操作ーー操作的确切性质将取决于被攻击的应用程序。由于 JavaScript 代码是由用户的浏览器执行的,因此对应用程序的请求包括会话 cookie,应用程序在用户不知情或未经用户同意的情况下执行操作。

如果表单元素不包含 action 属性ーー因为它是由具有 asp-controller、 asp-action 和 asp-page 属性的路由系统生成的ーー那么 FormTagHelper 类将自动启用反 CSRF 特性,即将安全令牌作为 cookie 添加到响应中。将包含相同安全令牌的隐藏输入元素添加到 HTML 表单中

Enabling the Anti-forgery Feature in a Controller

默认情况下,控制器接受 POST 请求,即使它们不包含所需的安全令牌

[AutoValidateAntiforgeryToken]
public class FormController : Controller

Enabling the Anti-forgery Feature in a Razor Page

防伪功能在 Razor 中默认启用

Using Anti-forgery Tokens with JavaScript Clients

默认情况下,防伪特性依赖于 ASP.NET Core 应用程序能够在 HTML 表单中包含一个元素,当表单提交时,浏览器会发回该元素。这对 JavaScript 客户端不起作用,因为 ASP.NET Core 应用程序提供数据而不是 HTML,所以没有办法插入隐藏元素并在将来的请求中接收它。

对于 Web 服务,防伪令牌可以作为 JavaScript 可读 cookie 发送,JavaScript 客户机代码读取该 cookie 并将其作为 POST 请求中的头文件包含在内

builder.Services.Configure<AntiforgeryOptions>(opts => {
    opts.HeaderName = "X-XSRF-TOKEN";
});

var app = builder.Build();

IAntiforgery antiforgery = app.Services.GetRequiredService<IAntiforgery>();
app.Use(async (context, next) => {
    if (!context.Request.Path.StartsWithSegments("/api")) {
        string? token = antiforgery.GetAndStoreTokens(context).RequestToken;
        if (token != null) {
            context.Response.Cookies.Append("XSRF-TOKEN",
               token,
               new CookieOptions { HttpOnly = false });
        }
    }
    await next();
});

需要一个自定义中间件组件来设置 cookie,在这个示例中,cookie 被命名为 XSRF-TOKEN。Cookie 的值是通过 IAntiForgery 服务获得的,必须将 HttpOnly 选项设置为 false,以便浏览器允许 JavaScript 代码读取 Cookie。

标签:Core,ASP,Helper,元素,应用程序,Tag,随记,public,属性
来源: https://www.cnblogs.com/huangwenhao1024/p/16439350.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有