Loading

ASP.NET Core 实战-8.使用标签助手构建表单

显示动态数据是许多 Web 应用程序的一个重要方面,但它通常只是故事的一半。 除了向用户显示数据之外,您通常还需要用户能够将数据提交回您的应用程序。 例如,您可以使用数据来自定义视图,或者通过将应用程序模型保存到数据库来更新应用程序模型。 对于传统的 Web 应用程序,这些数据通常使用 HTML 表单提交。

在第 5 章中,您了解了模型绑定,即如何接受用户在请求中发送的数据并将其转换为可在 Razor 页面中使用的 C# 对象。 您还了解了验证,以及验证请求中发送的数据的重要性。 您使用 DataAnnotations 属性来定义与模型关联的规则,以及其他关联的元数据,例如属性的显示名称。

我们还没有研究的最后一个方面是如何构建用户用来在请求中发送这些数据的 HTML 表单。 表单是用户在浏览器中与您的应用程序交互的主要方式之一,因此为您的应用程序正确定义它们并且对用户友好非常重要。 ASP.NET Core 提供了一个功能来实现这一点,称为标记帮助程序。

标记帮助程序是 ASP.NET Core 的新功能。 它们是 Razor 语法的补充,可用于自定义模板中生成的 HTML。 Tag Helpers 可以添加到其他标准 HTML 元素,例如 <input>,以根据您的 C# 模型自定义其属性,从而使您不必编写样板代码。Tag Helpers 也可以是独立元素,可用于 生成完全自定义的 HTML。

请记住,Razor 以及 Tag Helpers 用于服务器端 HTML 呈现。您不能直接在 Angular 或 React 等前端框架中使用 Tag Helpers

如果您使用过以前版本的 ASP.NET,那么 Tag Helpers 可能会让人想起 HTML Helpers,它也可以用于基于您的 C# 类生成 HTML。 标记帮助程序是 HTML 帮助程序的逻辑继承者,因为它们提供了比以前专注于 C# 的帮助程序更精简的语法。 HTML Helpers 在 ASP.NET Core 中仍然可用,因此如果您将一些旧模板转换为 ASP.NET Core,您仍然可以在模板中使用它们,但我不会在本书中介绍它们。

在本章中,您将主要学习如何在构建表单时使用标记助手。它们简化了生成正确元素名称和 ID 的过程,以便在将表单发送回您的应用程序时可以无缝地进行模型绑定。 为了将它们放在上下文中,您将继续构建您在前几章中看到的货币转换器应用程序。 您将添加向其提交货币兑换请求、验证数据以及使用 Tag Helpers 在表单上重新显示错误的功能,以便为您完成繁琐的工作,如图 8.1 所示。

在开发应用程序时,您会遇到使用表单时会遇到的最常见的 Tag Helpers。 您还将了解如何使用 Tag Helpers 来简化其他常见任务,例如生成链接、有条件地在应用程序中显示数据以及确保用户在刷新浏览器时看到最新版本的图像文件。

首先,我将讨论一下当 Razor 已经可以通过将 C# 和 HTML 组合到一个文件中来生成任何你喜欢的 HTML 时,为什么你需要 Tag Helpers。

图 8.1 使用 Tag Helpers 构建的货币转换器应用程序表单。标签、下拉菜单、输入元素和验证消息都是使用标签助手生成的。
image

使用标签助手迎合编辑

关于在 Razor 模板中混合使用 C# 和 HTML 的常见抱怨之一是您不能轻松地使用标准的 HTML 编辑工具。 C# 代码中的所有 @{} 符号往往会使编辑者感到困惑。 阅读模板对人们来说同样困难。 在 C# 和 HTML 之间切换范式有时会有点不协调。

当 Visual Studio 是构建 ASP.NET 网站的唯一受支持方式时,这可以说不是问题,因为它显然可以毫无问题地理解模板并有助于为编辑器着色。 但是随着 ASP.NET Core 跨平台的发展,与其他编辑器良好合作的愿望再次抬头。

这是 标签助手的一大动机。它们通过添加看起来像属性的东西无缝集成到标准 HTML 语法中,通常以 asp-* 开头。 它们最常用于生成 HTML 表单,如下面的清单所示。 此清单显示了货币转换器应用程序第一次迭代的视图,您可以在其中选择要转换的货币和数量。

清单 8.1 使用标签助手的用户注册表单

@page
@model ConvertModel //这是 Razor 页面 Convert.cshtml 的视图。模型类型是 ConvertModel。
<form method="post">
    <div class="form-group">
        <label asp-for="CurrencyFrom"></label>  //asp-for on Labels 根据视图模型为标签生成标题。
        //asp-for on Inputs 为模型生成正确的类型、值、名称和验证属性。
        <input class="form-control" asp-for="CurrencyFrom" />
        <span asp-validation-for="CurrencyFrom"></span>
    </div>
    <div class="form-group">
        <label asp-for="Quantity"></label>
        <input class="form-control" asp-for="Quantity" />
        <span asp-validation-for="Quantity"></span>
    </div>
    <div class="form-group">
        <label asp-for="CurrencyTo"></label>
        <input class="form-control" asp-for="CurrencyTo" />
        //使用标签助手将验证消息写入跨度。
        <span asp-validation-for="CurrencyTo"></span>
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
</form>

乍一看,您甚至可能没有发现标签助手,它们与 HTML 融合得非常好! 这使得使用任何标准 HTML 文本编辑器编辑文件变得容易。 但是不要担心你牺牲了 Visual Studio 中的可读性——如图 8.2 所示,带有标签助手的元素与标准 HTML <div> 元素和 <input> 上的标准 HTML 类属性明显不同元素. 被引用的视图模型的 C# 属性(在本例中为 CurrencyFrom)也仍然带有阴影,与 Razor 文件中的其他 C# 代码一样。 当然,正如您所期望的那样,您将获得 IntelliSense。

图 8.2 在 Visual Studio 中,Tag Helpers 通过粗体和不同颜色与普通元素区分开来,C# 带有阴影,并且 IntelliSense 可用。
image

标签助手是标准 HTML 元素(或完全是新元素)上的额外属性,通过修改它们附加到的 HTML 元素来工作。 它们使您可以轻松地将服务器端值(例如在 PageModel 上公开的值)与生成的 HTML 集成。

请注意,清单 8.1 没有指定要在标签中显示的标题。 相反,您以声明方式使用 asp-for="CurrencyFrom" 来表示,“对于这个 <label>,使用 CurrencyFrom 属性来计算要使用的标题。” 同样,对于 <input> 元素,Tag Helpers 用于

  • 自动填充 PageModel 属性的值。
  • 选择正确的 id 和名称,以便在将表单 POST 回 Razor 页面时,该属性将正确绑定模型。
  • 选择要显示的正确输入类型(例如,数量属性的数字输入)。
  • 显示任何验证错误,如图 8.3 所示。
图 8.3 Tag Helper 挂钩到 DataAnnotations 属性提供的元数据,以及属性类型本身。Validation Tag Helper 甚至可以根据 ModelState 填充错误消息,正如您在上一章验证中看到的那样。
image

使用标签助手创建表单

在本节中,您将学习如何使用一些最有用的标签助手:与表单一起使用的标签助手。 您将学习如何使用它们根据 PageModel 的属性生成 HTML 标记,创建正确的 idname 属性并将元素的值设置为模型属性的值(除其他外)。此功能显着减少了您需要手动编写的标记量。

假设您正在为货币转换器应用程序构建结帐页面,并且您需要在结帐页面上捕获用户的详细信息。 在第 5 章中,您构建了一个 UserBindingModel 模型(如清单 8.2 所示),添加了用于验证的 DataAnnotations 属性,并了解了如何在 POST 中将其模型绑定到 Razor 页面。 在本章中,您将看到如何通过将 UserBindingModel 公开为 PageModel 上的属性来为其创建视图。

使用 Razor Pages,您通常会在视图中公开相同的对象 用于模型绑定。当你这样做时,你必须小心不要在绑定模型中包含敏感值(不应该被编辑),以避免对你的应用程序进行大规模分配攻击

Listing 8.2 UserBindingModel for creating a user on a checkout page

public class UserBindingModel
{
    [Required]
    [StringLength(100, ErrorMessage = "Maximum length is {1}")]
    [Display(Name = "Your name")]
    public string FirstName { get; set; }
    [Required]
    [StringLength(100, ErrorMessage = "Maximum length is {1}")]
    [Display(Name = "Last name")]
    public string LastName { get; set; }
    [Required]
    [EmailAddress]
    public string Email { get; set; }
    [Phone(ErrorMessage = "Not a valid phone number.")]
    [Display(Name = "Phone number")]
    public string PhoneNumber { get; set; }
}

UserBindingModel 装饰有许多 DataAnnotations 属性。 在第 6 章中,您看到在执行页面处理程序之前,当模型绑定到请求时,在模型验证期间使用这些属性。 Razor 模板语言也使用这些属性来提供在使用标记帮助程序时生成正确 HTML 所需的元数据。

您可以使用我在第 6 章中描述的模式,将 UserBindindModel 公开为 PageModelInput 属性,以便在模型绑定和 Razor 视图中使用该模型:

public class CheckoutModel: PageModel
{
    [BindProperty]
    public UserBindingModel Input { get; set; }
}

UserBindingModel 属性、Tag Helpers 和一些 HTML 的帮助下,您可以创建一个 Razor 视图,让用户输入他们的详细信息,如图 8.4 所示。

图 8.4 应用程序的结帐页面。 HTML 基于 UserBindingModel 生成,使用 Tag Helpers 呈现所需的元素值、输入类型和验证消息。
image

生成此页面的 Razor 模板如清单 8.3 所示。 此代码使用各种标签助手,包括

<form> 元素上的表单标签助手
<label> 上的标签标签助手
<input> 上的输入标签助手
UserBindingModel 中每个属性的 <span> 验证元素上的验证消息标记帮助程序

清单 8.3 Razor 模板,用于在结帐页面上绑定到 UserBindingModel

@page
@model CheckoutModel //CheckoutModel 是 PageModel,它在 Input 属性上公开了一个 UserBindingModel。
@{
ViewData["Title"] = "Checkout";
}
<h1>@ViewData["Title"]</h1>
<form asp-page="Checkout"> //表单标签助手使用路由来确定表单将发布到的 URL。
    <div class="form-group">
        //Label Tag Helper 使用属性上的 DataAnnotations 来确定要显示的标题。
        <label asp-for="Input.FirstName"></label>
        <input class="form-control" asp-for="Input.FirstName" />
        <span asp-validation-for="Input.FirstName"></span>
    </div>
    <div class="form-group">
        <label asp-for="Input.LastName"></label>
        <input class="form-control" asp-for="Input.LastName" />
        <span asp-validation-for="Input.LastName"></span>
    </div>
    <div class="form-group">
        <label asp-for="Input.Email"></label>
        //Input Tag Helper 使用 DataAnnotations 来确定要生成的输入类型。
        <input class="form-control" asp-for="Input.Email" />
        <span asp-validation-for="Input.Email"></span>
    </div>
    <div class="form-group">
        <label asp-for="Input.PhoneNumber"></label>
        <input class="form-control" asp-for="Input.PhoneNumber" />
        //Validation Tag Helper 显示与给定属性关联的错误消息。
        <span asp-validation-for="Input.PhoneNumber"></span>
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
</form>

您可以在清单 8.4 中看到该模板生成的 HTML 标记。 这个 Razor 标记和生成的 HTML 产生了您在图 8.4 中看到的结果。 您可以看到每个带有 Tag Helper 的 HTML 元素都已在输出中自定义:<form> 元素具有 action 属性,<input> 元素具有基于引用属性名称的 idname,以及 <input><span> 都具有用于验证的 data-* 属性。

清单 8.4 结帐页面上 Razor 模板生成的 HTML

<form action="/Checkout" method="post">
    <div class="form-group">
        <label for="Input_FirstName">Your name</label>
        <input class="form-control" type="text"
               data-val="true" data-val-length="Maximum length is 100"
               id="Input_FirstName" data-val-length-max="100"
               data-val-required="The Your name field is required."
               Maxlength="100" name="Input.FirstName" value="" />
        <span data-valmsg-for="Input.FirstName"
              class="field-validation-valid" data-valmsg-replace="true"></span>
    </div>
    
    <div class="form-group">
        <label for="Input_LastName">Your name</label>
        <input class="form-control" type="text"
               data-val="true" data-val-length="Maximum length is 100"
               id="Input_LastName" data-val-length-max="100"
               data-val-required="The Your name field is required."
               Maxlength="100" name="Input.LastName" value="" />
        <span data-valmsg-for="Input.LastName"
              class="field-validation-valid" data-valmsg-replace="true"></span>
    </div>
    
    <div class="form-group">
        <label for="Input_Email">Email</label>
        <input class="form-control" type="email" data-val="true"
               data-val-email="The Email field is not a valid e-mail address."
               Data-val-required="The Email field is required."
               Id="Input_Email" name="Input.Email" value="" />
        <span class="text-danger field-validation-valid"
              data-valmsg-for="Input.Email" data-valmsg-replace="true"></span>
    </div>
    
    <div class="form-group">
        <label for="Input_PhoneNumber">Phone number</label>
        <input class="form-control" type="tel" data-val="true"
               data-val-phone="Not a valid phone number." Id="Input_PhoneNumber"
               name="Input.PhoneNumber" value="" />
        <span data-valmsg-for="Input.PhoneNumber"
              class="text-danger field-validation-valid"
              data-valmsg-replace="true"></span>
    </div>
    
    <button type="submit" class="btn btn-primary">Submit</button>
    <input name="__RequestVerificationToken" type="hidden"
           value="CfDJ8PkYhAINFx1JmYUVIDWbpPyy_TRUNCATED" />
</form>

哇,这是很多标记! 如果您是使用 HTML 的新手,这可能看起来有点让人不知所措,但要注意的重要一点是您不必编写大部分内容! 标签助手 为您处理了大部分管道。 简而言之,这基本上就是标签助手; 它们简化了构建 HTML 表单的繁琐机制,让您专注于应用程序的整体设计,而不是编写样板标记。

如果您使用 Razor 构建视图,Tag Helpers 将使您的生活更轻松,但它们完全是可选的。 您可以在没有它们的情况下自由编写原始 HTML,或使用旧版 HTML 助手。

标签助手 简化和抽象了 HTML 生成的过程,但它们通常会尝试这样做而不会妨碍您。 如果您需要最终生成的 HTML 具有特定属性,您可以将其添加到您的标记中。 你可以在前面看到 在 <input> 元素上定义类属性的列表,例如 <input class="form-control" asp-for="Input.FirstName" />。 它们原封不动地从 Razor 传递到 HTML 输出。

这与以前版本的 ASP.NET 中标签助手的工作方式不同; HTML 帮助程序通常需要在生成的标记中设置属性。

比这更好的是,您还可以设置通常由标签助手生成的属性,例如 <input> 元素上的 type 属性。 例如,如果您的 PageModel 上的 FavoriteColor 属性是一个字符串,那么默认情况下,Tag Helpers 将生成一个 type="text"<input> 元素。 更新您的标记以使用 HTML5 颜色选择器类型是微不足道的; 在 Razor 视图中明确设置类型:

<input type="color" asp-for="FavoriteColor" />

表单标签助手

毫无疑问,您需要开始构建 HTML 表单的第一件事是 <form> 元素。 在前面的示例中,<form> 元素增加了一个 asp-page 标签助手属性:

<form asp-page="Checkout">

这会导致在最终 HTML 中添加操作和方法属性,指示表单在提交时应该发送到哪个 URL 以及要使用的 HTTP 动词:

<form action="/Checkout" method="post">

设置 asp-page 属性允许您在应用程序中指定一个不同的 Razor 页面,表单将在提交时发布到该页面。 如果您省略 asp-page 属性,表单将回发到提供它的相同 URL。 这在 Razor Pages 中很常见。 您通常在用于显示它的同一 Razor 页面中处理表单发布的结果。

如果省略 asp-page 属性,则必须手动添加 method="post" 属性。 添加此属性很重要,以便使用 POST 动词而不是默认的 GET 动词发送表单。 将 GET 用于表单可能存在安全风险。

asp-page 属性由 FormTagHelper 添加。 这个标签助手使用提供的值来为动作属性生成一个 URL,使用我在第 4 章末尾描述的路由的 URL 生成特性。

标签助手可以使元素上的多个属性可用。 将它们想象成标签助手配置对象上的属性。 添加单个 asp- 属性会激活元素上的标签助手。添加其他属性可以让您覆盖其实现的更多默认值。

Form 标签助手使 <form> 元素上的其他几个属性可用,您可以使用这些属性来自定义生成的 URL。 希望你会记得在第 5 章中你可以在生成 URL 时设置路由值。 例如,如果您有一个名为 Product.cshtml 的 Razor 页面,它使用该指令

@page "{id}"

那么页面的完整路由模板将是“Product/{id}”。 要正确生成此页面的 URL,您必须提供 {id} 路由值。 如何使用 Form标签助手设置该值?

Form 标签助手定义了一个 asp-route-* 通配符属性,您可以使用它来设置任意路由参数。 将属性中的 * 设置为路由参数名称。 例如,要设置 id 路由参数,您需要设置 asp-route-id 值(在以下示例中显示为固定值 5,但更常见的是动态值):

<form asp-page="Product" asp-route-id="5">

基于 Product.cshtml Razor 页面的路由模板,这将生成以下标记:

<form action="/Product/5" method="post">

您可以根据需要向 <form> 添加尽可能多的 asp-route-* 属性,以生成正确的操作 URL。 您还可以将 Razor 页面处理程序设置为使用 asppage-handler 属性。 这确保表单 POST 将由您指定的处理程序处理。

Form 标签助手有许多附加属性,例如 asp-actionasp-controller,通常不需要与 Razor Pages 一起使用。 这些仅在您使用带有视图的 MVC 控制器时才有用。 特别要注意 asp-route 属性——这与 asp-route-* 属性不同。 前者用于指定命名路由(不与 Razor Pages 一起使用),后者用于指定在 URL 生成期间使用的路由值。

与所有其他 Razor 构造一样,您可以在标签助手中使用 PageModel(或一般的 C#)中的 C# 值。 例如,如果您的 PageModelProductId 属性包含 {id} 路由值所需的值,您可以使用

<form asp-page="Product" asp-route-id="@Model.ProductId">

Form 标签助手的主要工作是生成 action 属性,但它执行一项额外的重要功能:生成防止跨站点请求伪造 (CSRF) 攻击所需的隐藏 <input> 字段。

跨站点请求伪造 (CSRF) 攻击是一种网站漏洞,可以允许不相关的恶意网站在您的网站上执行操作。

您可以在清单 8.4 中的 <form> 底部看到生成的隐藏 <input>; 它被命名为 __RequestVerificationToken 并且包含一个看似随机的字符串。单标签助手默认生成它,因此您通常无需担心它,但如果您需要禁用它,您可以通过将 asp-antiforgery="false" 添加到您的 <form> 元素来实现。

标签标签助手

货币转换器应用程序中的每个 <input> 字段都需要有一个关联的标签,以便用户知道 <input> 的用途。 您可以轻松地自己创建这些,手动输入字段名称并根据需要设置 for 属性,但幸运的是,有一个标签助手可以为您做到这一点。

Label 标签助手用于根据 PageModel 中的属性为 <label> 元素生成标题(可见文本)和 for 属性。 它通过在 asp-for 属性中提供属性名称来使用:

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

Label 标签助手使用您在第 6 章中看到的 [Display] DataAnnotations 属性来确定要显示的适当值。 如果您为其生成标签的属性没有 [Display] 属性,则标签标签助手将使用该属性的名称。 考虑这个模型,其中 FirstName 属性具有 [Display] 属性,但 Email 属性没有:

public class UserModel
{
    [Display(Name = "Your name")]
    public string FirstName { get; set; }
    public string Email { get; set; }
}

以下 Razor

<label asp-for="FirstName"></label>
<label asp-for="Email"></label>

将生成此 HTML:

<label for="FirstName">Your name</label>
<label for="Email">Email</label>

<label> 元素内的标题文本使用在 [Display] 属性中设置的值,或者在 Email 属性的情况下使用属性名称。 另请注意,已使用属性名称生成 for 属性。 这是使用标签助手的一个关键优势——它与其他标签助手生成的元素 ID 挂钩,您很快就会看到。

for 属性对于可访问性很重要。 它指定标签所指的元素的 ID。 这对于使用屏幕阅读器的用户来说很重要,例如,因为他们可以知道表单字段与哪些属性相关。

除了 PageModel 上的属性外,您还可以引用子对象的子属性。 例如,正如我在第 6 章中所描述的,通常在 Razor 页面中创建一个嵌套类,将其作为属性公开,并使用 [BindProperty] 属性对其进行装饰:

public class CheckoutModel: PageModel
{
    [BindProperty]
    public UserBindingModel Input { get; set; }
}

您可以像在任何其他 C# 代码中一样,通过“point”到属性中来引用 UserBindingModelFirstName 属性。 清单 8.3 展示了更多这样的例子。

<label asp-for="Input.FirstName"></label>
<label asp-for="Input.Email"></label>

与 标签助手 一样,Label 标签助手不会覆盖您自己设置的值。 例如,如果您不想使用助手生成的标题,则可以手动插入自己的标题。 以下代码,

<label asp-for="Email">Please enter your Email</label>

将生成此 HTML:

<label for="Email">Please enter your Email</label>

与以往一样,如果您坚持标准约定并且不覆盖这样的值,您通常会更轻松地进行维护,但选项就在那里。 接下来是一个大问题:InputTextarea 标签助手。

InputTextarea 标签助手

现在你进入了表单的核心——处理用户输入的 <input> 元素。 鉴于有如此广泛的可能输入类型,它们可以在浏览器中以多种不同的方式显示。 例如,布尔值通常由复选框类型的 <input> 元素表示,而整数值将使用数字类型的 <input> 元素,而日期将使用日期类型,如图 8.5 所示。

图 8.5 各种输入元素类型。 每种类型的确切显示方式因浏览器而异。
image

为了处理这种多样性,Input 标签助手是最强大的标签助手之一。它使用基于属性类型(bool、string、int 等)和应用于它的任何 DataAnnotations 属性的信息([EmailAddress ][Phone] 等)来确定要生成的输入元素的类型。 DataAnnotations 还用于将 data-val-* 客户端验证属性添加到生成的 HTML。

考虑清单 8.2 中使用 [EmailAddress] 属性修饰的 Email 属性。 添加 <input> 就像使用 asp-for 属性一样简单:

<input asp-for="Input.Email" />

该属性是一个字符串,因此输入标记帮助程序通常会生成一个 type="text" 的 <input>。 但是添加 [EmailAddress] 属性提供了有关该属性的其他元数据。 因此,标签助手会生成一个带有 type="email" 的 HTML5 <input>

<input type="email" id="Input_Email" name="Input.Email"
       value="test@example.com" data-val="true"
       data-val-email="The Email Address field is not a valid e-mail address."
       Data-val-required="The Email Address field is required."
       />

你可以从这个例子中拿走很多东西。 首先,HTML 元素的 idname 属性是根据属性的名称生成的。 id 属性的值与 Label 标签助手在其 for 属性 Input_Email 中生成的值相匹配。 name 属性的值保留“点”表示法 Input.Email,以便在将字段 POST 到 Razor 页面时模型绑定正常工作。

此外,该字段的初始值已设置为当前存储在属性中的值(在本例中为“test@example.com”)。 元素的类型也被设置为 HTML5 电子邮件类型,而不是使用默认的文本类型。

也许最引人注目的添加是大量的 data-val-* 属性。 客户端 JavaScript 库(例如 jQuery)可以使用这些来提供对 DataAnnotations 约束的客户端验证。 当用户输入的值无效时,客户端验证向用户提供即时反馈,提供比单独使用服务器端验证更流畅的用户体验,如我在第 6 章中所述。

客户端验证

为了在您的应用程序中启用客户端验证,您需要将一些 jQuery 库添加到您的 HTML 页面。 特别是,您需要包含 jQuery、jQuery-validation 和 jQuery-validation-unobtrusive JavaScript 库。 您可以通过多种方式执行此操作,但最简单的方法是将脚本文件包含在视图底部,使用

<script src="~/lib/jqueryvalidation/
             dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validationunobtrusive/
             jquery.validate.unobtrusive.min.js"></script>

默认模板为您包括这些脚本,在一个方便的部分模板中,您可以在脚本部分添加到您的页面。 如果您使用默认布局并且需要将客户端验证添加到视图中,请在视图中的某处添加以下部分:

@section Scripts{
@Html.Partial("_ValidationScriptsPartial")
}

此部分视图引用您 wwwroot 文件夹中的文件。 默认的 _layout 模板包含 jQuery 本身,这是前端组件库 Bootstrap 所要求的。

Input标签助手尝试根据 DataAnnotations 属性或属性类型为给定属性选择最合适的模板。 这是否生成您需要的确切 <input> 类型可能在一定程度上取决于您的应用程序。与往常一样,您可以通过将自己的 type 属性添加到 Razor 模板中的元素来覆盖生成的类型。 表 8.1 显示了一些常见的数据类型如何映射到 <input> 类型,以及如何指定数据类型本身。

表 8.1 常见数据类型、如何指定它们以及它们映射到的输入元素类型

数据类型 如何指定 输入元素类型
byte, int, short,
long, uint
属性类型 number
decimal, double,
float
属性类型 text
bool 属性类型 checkbox
string Property type, [DataType(DataType.Text)]
attribute
text
HiddenInput [HiddenInput] attribute hidden
Password [Password] attribute password
Phone [Phone] attribute tel
EmailAddress [EmailAddress] attribute email
Url [Url] attribute url
Date DateTime property type,
[DataType(DataType.Date)] attribute
date

Input 标签助手有一个附加属性,可用于自定义数据的显示方式:asp-format。 HTML 表单完全基于字符串,因此当设置 <input> 的值时,Input 标签助手必须获取存储在属性中的值并将其转换为字符串。 在幕后,这会对属性的值执行 string.Format(),并传入格式字符串。

Input 标签助手为每种不同的数据类型使用默认格式字符串,但使用 asp-format 属性,您可以设置要使用的特定格式字符串。 例如,您可以确保将小数属性 Dec 格式化为小数点后三位 以下代码:

<input asp-for="Dec" asp-format="{0:0.000}" />

如果 Dec 属性的值为 1.2,则生成的 HTML 类似于

<input type="text" id="Dec" name="Dec" value="1.200">

您可能会对小数和双精度类型呈现为文本字段而不是数字字段感到惊讶。 这是由于几个技术原因,主要与某些文化用逗号和空格呈现数字的方式有关。 呈现为文本可避免仅出现在某些浏览器文化组合中的错误。

除了 Input 标签助手,ASP.NET Core 还提供了 Textarea 标签助手。 这以类似的方式工作,使用 asp-for 属性,但它附加到 <textarea> 元素:

<textarea asp-for="BigtextValue"></textarea>

这会生成类似于以下内容的 HTML。请注意,属性值在标记内呈现,并且 data-val-* 验证元素照常附加:

<textarea data-val="true" id="BigtextValue" name="BigtextValue"
          data-val-length="Maximum length 200." data-val-length-max="200"
          data-val-required="The Multiline field is required." >This is some text,
    I'm going to display it
    in a text area</textarea>

希望本节已经敲定了 标签助手 可以减少多少打字,尤其是在将它们与 DataAnnotations 结合使用以生成验证属性时。 但这不仅仅是减少所需的击键次数; 标签助手确保生成的标记是正确的,并且具有正确的nameidstyle,以便在将绑定模型发送到服务器时自动绑定它们。

借助 <form><label><input>,您可以构建大部分货币转换器表单。 在我们查看显示验证消息之前,还有一个元素需要查看:<select> 或下拉输入。

选择标签助手

除了 <input> 字段,您将在 Web 表单上看到的一个常见元素是 <select> 元素,或者下拉列表和列表框。 例如,您的货币转换器应用程序可以使用 <select> 元素让您从列表中选择要转换的货币。

默认情况下,此元素显示项目列表并让您选择一个,但有几种变体,如图 8.6 所示。 除了普通的下拉框外,您还可以显示列表框、添加多选或分组显示列表项。

图 8.6 使用 Select 标签助手 显示 <select> 元素的多种方式中的一些。
image

要在 Razor 代码中使用 <select> 元素,您需要在 PageModel 中包含两个属性:一个用于显示选项列表的属性,另一个用于保存所选值。 例如,清单 8.5 显示了 PageModel 上用于创建图 8.6 所示的三个最左侧选择列表的属性。 显示组需要稍微不同的设置,您很快就会看到。

清单 8.5 显示选择元素下拉列表和列表框的视图模型

public class SelectListsModel: PageModel
{
    [BindProperty]
    public class InputModel Input { get; set; } //InputModel 用于将用户的选择绑定到选择框
    //要在选择框中显示的项目列表
    public IEnumerable<SelectListItem> Items { get; set; }
    = new List<SelectListItem>
    {
        new SelectListItem{Value= "csharp", Text="C#"},
        new SelectListItem{Value= "python", Text= "Python"},
        new SelectListItem{Value= "cpp", Text="C++"},
        new SelectListItem{Value= "java", Text="Java"},
        new SelectListItem{Value= "js", Text="JavaScript"},
        new SelectListItem{Value= "ruby", Text="Ruby"},
    };
    public class InputModel
    {
        //这些属性将保存由单选选择框选择的值。
        public string SelectedValue1 { get; set; }
        public string SelectedValue2 { get; set; }
        //要创建多选列表框,请使用 IEnumerable<>。
        public IEnumerable<string> MultiValues { get; set; }
    }
}

此清单演示了使用 <select> 列表的许多方面:

  • SelectedValue1/SelectedValue2 - 用于保存用户选择的值。它们与从下拉/列表框中选择的值绑定模型,并用于在呈现表单时预选正确的项目。
  • MultiValues - 用于保存多选列表的选定值。 它是一个 IEnumerable,因此每个 <select> 元素可以容纳多个选择。
  • Items - 提供要在 <select> 元素中显示的选项列表。 请注意,元素类型必须是 SelectListItem,它公开了 ValueText 属性,才能与 Select 标签助手一起使用。 这不是 InputModel 的一部分,因为我们不想将这些项目模型绑定到请求 - 它们通常会直接从应用程序模型加载或硬编码。

Select 标签助手仅适用于 SelectListItem 元素。 这意味着您通常必须从特定于应用程序的项目列表集(例如,List<string>List<MyClass>)转换为以 UI 为中心的 List<SelectListItem>

Select 标签助手公开了您可以添加到 <select> 元素的 asp-forasp-items 属性。 至于 Input 标签助手,asp-for 属性指定了 PageModel 中要绑定的属性。 为 标签助手提供了 asp-items 属性以显示可用的 <option> 元素。

希望在 <select> 列表中显示枚举选项列表是很常见的。这很常见,以至于 ASP.NET Core 附带了一个帮助器,用于为任何枚举生成 SelectListItem。 如果你有一个 TEnum 类型的枚举,你可以使用 asp-items="Html.GetEnumSelectList<TEnum>()" 在你的视图中生成可用的选项。

以下清单显示了如何显示下拉列表、单选列表框和多选列表框。 它使用上一个清单中的 PageModel,将每个 <select> 列表绑定到不同的属性,但为所有这些重复使用相同的 Items 列表。

清单 8.6 以三种不同方式显示选择元素的 Razor 模板

@page
@model SelectListsModel
<select asp-for="Input.SelectedValue1"
        asp-items="Model.Items"></select> //通过绑定到 asp-for 中的标准属性来创建标准下拉选择列表
<select asp-for="Input.SelectedValue2"
        asp-items="Model.Items" size="4"></select> //通过提供标准 HTML 大小属性创建一个高度为 4 的单选列表框
<select asp-for="Input.MultiValues"
        asp-items="Model.Items"></select> //通过绑定到 asp-for 中的 IEnumerable 属性来创建多选列表框

希望您能看到用于生成下拉 <select> 列表的 Razor 与用于生成多选 <select> 列表的 Razor 几乎相同。 如果绑定的属性是 IEnumerable,则 Select 标签助手负责将多个 HTML 属性添加到生成的输出中。

asp-for 属性不得包含 Model. 前缀。 另一方面,如果引用 PageModel 上的属性,则 asp-items 属性必须包含它。 asp-items 属性还可以引用其他 C# 项,例如存储在 ViewData 中的对象,但使用 PageModel 属性是最好的方法。

到目前为止,您已经看到了如何绑定三种不同类型的选择列表,但是我在图 8.6 中还没有涉及到如何使用 <optgroup> 元素在列表框中显示组。 幸运的是,您的 Razor 代码无需更改; 您只需要更新您定义 SelectListItems 的方式。

SelectListItem 对象定义了一个 Group 属性,该属性指定项目所属的 SelectListGroup。 下面的清单显示了如何使用类似于清单 8.5 所示的 PageModel 创建两个组并将每个列表项分配给“动态”或“静态”组。 最后一个列表项 C# 没有分配给组,因此它将正常显示,没有 <optgroup>

清单 8.7 添加组到 SelectListItems 以创建 optgroup 元素

public class SelectListsModel: PageModel
{
    [BindProperty]
    public IEnumerable<string> SelectedValues { get; set; } //用于保存允许多选的选定值
    public IEnumerable<SelectListItem> Items { get; set; }
    public SelectListsModel() //在构造函数中初始化列表项
    {
        ////创建每个组的单个实例以传递给 SelectListItems
        var dynamic = new SelectListGroup { Name = "Dynamic" };
        var stat = new SelectListGroup { Name = "Static" }; 
        Items = new List<SelectListItem>
        {
            new SelectListItem {
                Value= "js",
                Text="Javascript",
                Group = dynamic //为每个 SelectListItem 设置适当的组
            },
            new SelectListItem {
                Value= "cpp",
                Text="C++",
                Group = stat
            },
            new SelectListItem {
                Value= "python",
                Text="Python",
                 roup = dynamic //为每个 SelectListItem 设置适当的组
             },
            new SelectListItem { //如果 SelectListItem 没有组,则不会将其添加到 <optgroup>。
                Value= "csharp",
                Text="C#",
            }
        };
    }
}

有了这个,Select 标签助手将在将 Razor 呈现为 HTML 时根据需要生成 <optgroup> 元素。 这个Razor 模板,

@page
@model SelectListsModel
<select asp-for="SelectedValues" asp-items="Model.Items"></select>

将呈现为 HTML,如下所示:

<select id="SelectedValues" name="SelectedValues" multiple="multiple">
    <optgroup label="Dynamic">
        <option value="js">JavaScript</option>
        <option value="python">Python</option>
    </optgroup>
    <optgroup label="Static Languages">
        <option value="cpp">C++</option>
    </optgroup>
    <option value="csharp">C#</option>
</select>

使用 <select> 元素时的另一个常见要求是在列表中包含一个选项,表明没有选择任何值,如图 8.7 所示。如果没有这个额外的选项,默认的 <select> 下拉菜单将始终有一个 值,它将默认为列表中的第一项。

您可以通过以下两种方式之一实现此目的:您可以将“未选择”选项添加到可用的 SelectListItems,或者您可以手动将选项添加到 Razor,例如使用

<select asp-for="SelectedValue" asp-items="Model.Items">
    <option Value = "">**Not selected**</option>
</select>

这将在 <select> 元素的顶部添加一个额外的 <option>,带有一个空白的 Value 属性,允许您为用户提供“无选择”选项。

<select> 元素添加“无选择”选项非常常见,您可能希望创建一个局部视图来封装此逻辑。

图 8.7 如果没有“未选择”选项,<select> 元素将始终有一个值。 如果您不希望默认选择 <option>,这可能不是您想要的行为。
image

借助 Input标签助手和 Select标签助手,您应该能够创建所需的大部分表单。 您现在拥有创建货币转换器应用程序所需的所有部件,但有一个例外。

请记住,无论何时您接受来自用户的输入,您都应该始终验证数据。 Validation 标签助手提供了一种在表单上向用户显示模型验证错误的方法,而无需编写大量样板标记。

验证消息和验证摘要标签助手

在第 8.2.3 节中,您看到 Input 标签助手在表单输入元素本身上生成必要的 data-val-* 验证属性。 但是您还需要在某个地方显示验证消息。 这可以通过使用 asp-validation-for 属性应用到 <span>Validation Message 标签助手为视图模型中的每个属性实现:

<span asp-validation-for="Email"></span>

当客户端验证期间发生错误时,被引用属性的相应错误消息将显示在 <span> 中,如图 8.8 所示。 如果服务器端验证失败并且正在重新显示表单,则此 <span> 元素也将用于显示适当的验证消息。

图 8.8 验证消息可以通过使用验证消息标签助手显示在关联的 <span> 中。
image

与存储在 ModelState 中的 Email 属性相关的任何错误都将呈现在元素主体中,并且该元素将具有适当的属性以挂钩到 jQuery 验证:

<span class="field-validation-valid" data-valmsg-for="Email"
data-valmsg-replace="true">The Email Address field is required.</span>

当用户更新电子邮件 <input> 字段并执行客户端验证时,将替换元素中显示的验证错误。

除了显示单个属性的验证消息外,您还可以使用 Validation Summary Tag Helper

中显示所有验证消息的摘要,如图 8.9 所示。 这会呈现一个包含 ModelState 错误列表的 <ul>

图 8.9 显示验证错误的表单。 Validation Message 标签助手 应用于 <span>,靠近关联的输入。 Validation Summary 标签助手 应用于 <div>,通常位于表单的顶部或底部。
image

Validation Summary 标签助手使用 asp-validationsummary 属性应用于 <div> 并提供 ValidationSummary 枚举值,例如

<div asp-validation-summary="All"></div>

ValidationSummary 枚举控制显示哪些值,它具有三个可能的值:

  • None - 不显示摘要。 (我不知道你为什么要使用它。)
  • ModelOnly - 仅显示与属性无关的错误。
  • All - 显示与属性或模型相关的错误。

如果您有与页面相关的错误并非特定于单个属性,则验证摘要标记帮助程序特别有用。 这些可以通过使用空白键添加到模型状态,如清单 8.8 所示。 在这个例子中,属性验证通过了,但我们提供了额外的模型级验证来检查我们是否没有尝试将货币转换为自身。

清单 8.8 向 ModelState 添加模型级验证错误

public class ConvertModel : PageModel
{
    [BindProperty]
    public InputModel Input { get; set; }
    [HttpPost]
    public IActionResult OnPost()
    {
        if(Input.CurrencyFrom == Input.CurrencyTo) //无法将货币转换为自身
        {
            //通过使用空键添加模型级错误,不绑定到特定属性
            ModelState.AddModelError(
                string.Empty,
                "Cannot convert currency to itself");
        }
        //如果有任何属性级别或模型级别的错误,请显示它们。
        if (!ModelState.IsValid)
        {
            return Page();
        }
        //store the valid values somewhere etc
        return RedirectToPage("Checkout");
    }
}

如果没有 Validation Summary 标签助手,如果用户两次使用相同的货币,仍然会添加模型级错误,并且会重新显示表单。 不幸的是,用户没有视觉提示来指示表单未提交的原因——显然这是一个问题! 通过添加 Validation Summary标签助手,模型级错误会显示给用户,以便他们纠正问题,如图 8.10 所示。

为简单起见,我将验证检查添加到页面处理程序。 更好的方法可能是创建一个自定义验证属性来实现这一点。 这样,您的处理程序将保持精益并坚持单一责任原则。

图 8.10 模型级错误仅由 Validation Summary标签助手显示。 没有一个,用户将不会有任何迹象表明表单上有错误,因此将无法更正它们。
image

本节介绍了大多数可用于处理表单的常见标签助手,包括构建货币转换器表单所需的所有部分。 它们应该为您提供在您自己的应用程序中开始构建表单所需的一切。但表单并不是标签助手有用的唯一领域; 它们通常适用于您需要将服务器端逻辑与 HTML 生成混合的任何时候。

一个这样的示例是使用基于路由的 URL 生成来生成指向应用程序中其他页面的链接。 鉴于路由被设计为在您重构应用程序时是流畅的,如果您必须手动进行,那么跟踪链接应该指向的确切 URL 将是一个维护噩梦。 如您所料,有一个标签助手:锚标签助手。

使用 Anchor 标签助手生成链接

在第 4 章末尾,我展示了如何使用 ActionResults 从页面处理程序内部生成指向应用程序中其他页面的链接的 URL。通常,视图是您需要链接到应用程序中其他页面的另一个常见位置 通过带有指向相应 URL 的 href 属性的 <a> 元素。

在本节中,我将展示如何使用 Anchor 标签助手通过路由为给定的 Razor 页面生成 URL。从概念上讲,这与 Form 标签助手生成操作 URL 的方式几乎相同,如您在第 8.2.1 节中所见。为了大多数情况下,使用 Anchor标签助手也是相同的; 您提供 asp-pageasp-page-handler 属性,以及必要时的 asp-route-* 属性。 默认 Razor 页面模板使用 Anchor 标签助手使用以下清单中的代码生成导航栏中显示的链接。

清单 8.9 使用 Anchor 标签助手 在 _Layout.cshtml 中生成 URL

<ul class="navbar-nav flex-grow-1">
    <li class="nav-item">
        <a class="nav-link text-dark"
           asp-area="" asp-page="/Index">Home</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-dark"
           asp-area="" asp-page="/Privacy">Privacy</a>
    </li>
</ul>

如您所见,每个 <a> 元素都有一个 asp-page 属性。 此 标签助手使用路由系统为 <a> 生成适当的 URL,从而产生以下标记:

<ul class="nav navbar-nav">
    <li class="nav-item">
        <a class="nav-link text-dark" href="/">Home</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-dark" href="/Privacy">Privacy</a>
    </li>t
</ul>

URL 尽可能使用默认值,因此 Index Razor 页面生成简单的“/” URL,而不是“/Index”。

如果您需要对生成的 URL 进行更多控制,Anchor 标签助手会公开几个您可以设置的附加属性,这些属性将在 URL 生成期间使用。 这些是 Razor 页面最常用的:

  • asp-page - 设置要执行的 Razor 页面。
  • asp-page-handler - 设置要执行的 Razor 页面处理程序。
  • asp-area - 设置要使用的区域路由参数。 区域可用于为您的应用程序提供额外的组织层。
  • asp-host - 如果设置,链接将指向提供的主机,并将生成绝对 URL 而不是相对 URL。
  • asp-protocol - 设置是否生成 http 或 https 链接。 如果设置,它将生成一个绝对 URL 而不是相对 URL。
  • asp-route-* - 设置生成期间使用的路由参数。 可以针对不同的路由参数多次添加。

通过使用 Anchor 标签助手及其属性,您可以使用路由系统生成 URL,如第 4 章所述。这通过删除您需要嵌入所有视图中的硬编码 URL 来减少代码中的重复。

如果您发现自己在标记中编写重复代码,则很可能有人编写了标签助手来帮助它。 下一节中的 Append Version 标签助手是使用 标签助手 减少所需繁琐代码量的一个很好的例子。

使用 Append Version 标签助手清除缓存

在开发和应用程序投入生产时,Web 开发的一个常见问题是确保浏览器都使用最新的文件。 出于性能原因,浏览器通常会在本地缓存文件并将其重用于后续请求,而不是在每次请求文件时调用您的应用程序。

通常这很好 - 您站点中的大多数静态资产很少更改,因此缓存它们可以显着减少服务器的负担。 想一想您公司徽标的图像——它多久变化一次? 如果每个页面都显示您的徽标,那么在浏览器中缓存图像就很有意义。

但如果它真的改变了会发生什么? 您希望确保用户在可用时立即获得更新的资产。 更关键的要求可能是与您的站点关联的 JavaScript 文件是否更改。 如果用户最终使用 JavaScript 的缓存版本,他们可能会看到奇怪的错误,或者您的应用程序可能会在他们看来已损坏。

这个难题在 Web 开发中很常见,处理它的最常见方法之一是使用缓存清除查询字符串。

缓存清除查询字符串将查询参数添加到 URL,例如 ?v=1。 浏览器将缓存响应并将其用于对 URL 的后续请求。 当资源改变时,查询字符串也会改变,例如变为?v=2。 浏览器会将此视为对新资源的请求,并将发出新请求。

这种方法的最大问题是它要求您在每次images、CSS 或 JavaScript 文件更改时更新 URL。 这是一个手动步骤,需要更新引用资源的每个位置,因此不可避免地会出现错误。 标记助手来救援! 当您向应用程序添加 <script><img><link> 元素时,您可以使用标签助手 自动生成 cachebusting 查询字符串:

<script src="~/js/site.js" asp-append-version="true"></script>

asp-append-version 属性将加载被引用的文件并根据其内容生成唯一的哈希。 然后将其作为唯一查询字符串附加到资源 URL:

<script src="/js/site.js?v=EWaMeWsJBYWmL2g_KkgXZQ5nPe"></script>

由于这个值是文件内容的哈希值,只要文件没有被修改,它就保持不变,所以文件会被缓存在用户的浏览器中。 但是如果文件被修改,内容的哈希值会改变,查询字符串也会改变。 这确保浏览器始终为您的应用程序提供最新的文件,而无需担心在更改文件时手动更新每个 URL。

到目前为止,在本章中,您已经了解了如何使用标签助手进行表单、链接生成和缓存清除。 您还可以使用标签助手根据当前环境有条件地呈现不同的标记。 这使用了一种您尚未见过的技术,其中标签助手被声明为一个完全独立的元素。

将条件标记与 Environment标签助手一起使用

在许多情况下,您希望根据您的网站是在开发环境还是生产环境中运行,在 Razor 模板中呈现不同的 HTML。 例如,在开发中,您通常希望 JavaScript 和 CSS 资产冗长且易于阅读,但在生产中,您会处理这些文件以使其尽可能小。 另一个例子可能是希望在应用程序在测试环境中运行时将横幅应用到应用程序,当您转移到生产环境时将其删除,如图 8.11 所示。

图 8.11 每当您在测试环境中运行时,都会显示警告横幅,以便与生产环境区分开来。
image

您已经了解了如何使用 C# 将 if 语句添加到您的标记中,因此当当前环境具有给定值时,完全可以使用此技术向您的标记中添加一个额外的 div。 如果我们假设 env 变量包含当前环境,您可以使用如下内容:

@if(env == "Testing" || env == "Staging")
{
	<div class="warning">You are currently on a testing environment</div>
}

这并没有什么问题,但更好的方法是使用标签助手范例来保持您的标记干净且易于阅读。 幸运的是,ASP.NET Core 附带了 EnvironmentTagHelper,它可用于以稍微清晰的方式实现相同的结果:

<environment include="Testing,Staging">
	<div class="warning">You are currently on a testing environment</div>
</environment>

这个标签助手与您之前看到的其他标签助手有点不同。 整个元素是标签助手,而不是使用 asp- 属性来扩充现有的 HTML 元素。 这个标签助手完全负责生成标记,它使用一个属性来配置它。

在功能上,这个标签助手与 C# 标记相同(尽管现在我已经掩盖了如何找到 env 变量),但它的功能比 C# 替代方案更具声明性。 您显然可以随意使用任何一种方法,但我个人喜欢标签助手的类似 HTML 的性质。

我们已经到了本章关于标签助手的结尾,有了它,我们第一次看到了构建向用户显示 HTML 的传统 Web 应用程序。 在本书的最后一部分,我们将重温 Razor 模板,您将学习如何构建自定义组件,如自定义 标签助手 和视图组件。 现在,您拥有构建复杂 Razor 布局所需的一切——自定义组件可以帮助整理您的代码。

总结

  • 使用标签助手,您可以将数据模型绑定到 HTML 元素,从而更轻松地生成动态 HTML,同时保持编辑器友好。
  • 与一般的 Razor 一样,标签助手 仅用于 HTML 的服务器端呈现。 你不能直接在前端框架中使用它们,比如 Angular 或 React。
  • 标签助手 可以是独立的元素,也可以使用属性附加到现有的 HTML。 这使您既可以自定义 HTML 元素,也可以添加全新的元素。
  • 标签助手 可以自定义它们附加到的元素,添加其他属性,并自定义它们如何呈现为 HTML。 这可以大大减少您需要编写的标记量。
  • 标签助手可以在单个元素上公开多个属性。 这使得配置标签助手 变得更加容易,因为您可以设置多个单独的值。
  • 您可以将 asp-pageasp-page-handler 属性添加到 <form> 元素,以使用 Razor Pages 的 URL 生成功能设置操作 URL。
  • 您可以使用 asp-route-* 属性通过 Form 标签助手指定要在路由期间使用的路由值。 这些值用于构建最终 URL 或作为查询数据传递。
  • Form Tag Helper 还会生成一个隐藏字段,您可以使用它来防止 CSRF 攻击。 这是自动添加的,是一项重要的安全措施。
  • 您可以使用 asp-for 将 Label 标签助手附加到 <label>。 它根据 [Display] Data-Annotations 属性和 PageModel 属性名称生成适当的属性和标题。
  • Input 标签助手根据绑定属性的 Type 和应用于它的任何 DataAnnotations<input> 元素的 type 属性设置为适当的值。 它还生成客户端验证所需的 data-val-* 属性。 这显着减少了您需要编写的 HTML 代码量。
  • 要启用客户端验证,您必须将必要的 JavaScript 文件添加到您的视图中以进行 jQuery 验证和不显眼的验证。
  • Select 标签助手可以使用 asp-for 和 asp-items 属性生成下拉 <select> 元素以及列表框。 要生成多选 <select> 元素,请将元素绑定到视图模型上的 IEnumerable 属性。 您可以使用这些方法来生成几种不同样式的选择框。
  • asp-for 中提供的项目必须是 IEnumerable<SelectListItem>。 如果您尝试绑定其他类型,您将在 Razor 视图中收到编译时错误。
  • 您可以使用 Html.GetEnumSelectList<TEnum>() 辅助方法为枚举 TEnum 生成 IEnumerable<SelectListItem>。 这使您不必自己编写映射代码。
  • 如果 asp-for 中提供的项目在 Group 属性上具有关联的 SelectListGroup,则 Select 标签助手将生成 <optgroup> 元素。 组可用于分隔选择列表中的项目。
  • 添加到 Razor 标记的任何额外的附加 <option> 元素都将传递到最终的 HTML。 您可以使用这些附加元素轻松地向 <select> 元素添加“无选择”选项。
  • Validation Message 标签助手用于呈现给定属性的客户端和服务器端验证错误消息。 当元素出现错误时,这会向您的用户提供重要的反馈。 使用 asp-validation-for 属性将 Validation Message 标签助手附加到 <span>
  • Validation Summary 标签助手用于显示模型以及单个属性的验证错误。 您可以使用模型级属性来显示不仅仅适用于一个属性的附加验证。 使用 asp-validation-summary 属性将 Validation Summary标签助手附加到 <div>
  • 您可以使用 Anchor 标签助手生成 <a> URL。 这个助手使用路由来生成使用 asp-page、asp-page-handler 和 asp-route-* 属性的 href URL,为您提供路由的全部功能。
  • 您可以将 asp-append-version 属性添加到 <link><script><img> 元素,以提供基于文件内容的缓存清除功能。 这可确保用户出于性能原因缓存文件,但仍始终获得最新版本的文件。
  • 您可以使用 Environment 标签助手根据应用程序的当前执行环境有条件地呈现不同的 HTML。 如果您愿意,可以使用它在不同的环境中呈现完全不同的 HTML。
posted @ 2022-09-03 18:05  F(x)_King  阅读(240)  评论(0编辑  收藏  举报