首页 > 编程语言 >ASP.NET Core应用程序10:使用表单标签助手

ASP.NET Core应用程序10:使用表单标签助手

时间:2024-06-13 19:43:18浏览次数:12  
标签:Core ASP Form 10 元素 视图 表单 asp 属性

  本章描述用于创建 HTML 表单的内置标签助手。这些标签助手确保表单提交到正确的操作或页面处理程序方法,并确保元素准确地表示特定的模型属性。
  本章解释 ASP.NET Core 提供的创建 HTML 表单的功能。展示如何使用标签助手来选择表单目标和关联的 imput、textarea 和 select 元素。

1 准备工作

  本章使用了前一章中的项目。
  为准备这一章,替换 Views/Shared 文件夹的 _SimpleLayout.cshtml 文件中的内容。

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
    <div class="m-2">
        @RenderBody()
    </div>
</body>
</html>

  本章使用控制器视图和 Razor Pages 来呈现相似的内容。为了更容易区分控制器和页面,将如下所示的路由添加到 Startup 类中。

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapControllerRoute("forms",
        "controllers/{controller=Home}/{action=Index}/{id?}");
    endpoints.MapDefaultControllerRoute();
    endpoints.MapRazorPages();
});

  新路由引入了一个静态路径段,使 URL 明显地以控制器为目标。使用浏览器请求http://localhost:5000/controllers/home/list,这会显示一个产品列表。

2 理解表单处理模式

  大多数 HTML 表单如下图所示处理数据。首先,浏览器发送一个 HTTP GET 请求,这会生成一个包含表单的 HTML 响应,使用户能够向应用程序提供数据。用户单击一个按钮使用 HTTP POST 请求提交表单数据,应用程序接收和处理用户的数据,处理完数据后发送一个响应将浏览器重定向到一个 URL,该 URL 提供了对用户操的确认。
image
  这称为 Post/Redirect/Get 模式,这个重定向很重要,因为它意味着用户可以单击浏览器的 reload 按钮而不发送另一个 Post 请求,不然可能会导致无意中重复操作。

2.1 创建控制器来处理表单

  处理表单的控制器是通过结合前面章节中描述的特性创建的。在 Controllers 文件夹中添加一个名为 FormController.cs 的类文件。

public class FormController : Controller
{
    private DataContext context;
    public FormController(DataContext dbContext)
    {
        context = dbContext;
    }
    public async Task<IActionResult> Index(long id = 1)
    {
        return View("Form", await context.Products.FindAsync(id));
    }
    [HttpPost]
    public IActionResult SubmitForm()
    {
        var data = Request.Form.Keys.Where(k => !k.StartsWith(""));
        foreach (string key in data)
        {
            TempData[key] = string.Join(",", Request.Form[key]);
        }
        return RedirectToAction(nameof(Results));
    }
    public IActionResult Results()
    {
        return View(TempData);
    }
}

  Index 操作方法选择一个名为 Form 的视图,它向用户呈现一个 HTML 表单。
  当用户提交表单时,它由 SubmitForm 操作只能接收 HTTP POST 请求。这个操作方法处理通过 Request.Form 属性得到的 HTML 表单数据,以便可以使用临时数据特性存储它。每个表单数据值都以字符串数组的形式呈现,将其转换为以逗号分隔的字符串用于存储。浏览器重定向到 Results 操作方法,该方法选择默认视图并提供临时数据作为视图模型。

  创建 Views/From 文件夹,添加 From.cshtml 视图文件。

@model Product
@{
    Layout = "_SimpleLayout";
}

<h5 class="bg-primary text-white text-center p-2">HTML Form</h5>

<form action="/controllers/form/submitform" method="post">
    <div class="form-group">
        <label>Name</label>
        <input class="form-control" name="Name" value="@Model.Name" />
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
</form>

  这个视图包含一个简单的 HTML 表单,配置为使用 POST 请求将数据提交给 Submitfom 方法。表单包含一个imput 元素,该元素的值是使用 Razor 表达式设置的。接下来给 Views/From 文件夹添加一个名为 Results.cshtml 的 Razor 视图。

@model TempDataDictionary
@{
    Layout = "_SimpleLayout";
}
<table class="table table-striped table-bordered table-sm">
    <thead>
        <tr class="bg-primary text-white text-center">
            <th colspan="2">Form Data</th>
        </tr>
    </thead>
    <tbody>
        @foreach (string key in Model.Keys)
        {
            <tr>
                <th>@key</th>
                <td>@Model[key]</td>
            </tr>
        }
    </tbody>
</table>
<a class="btn btn-primary" asp-action="Index">Return</a>

  这个视图向用户显示表单数据。并使用浏览器请求 http:/localhost:5000/controllers/form 以査看 HTML表单。在文本字段中输入一个值,并单击 Submit 发送一个 POST 请求,该请求将由 SubmitForm 操作处理。表单数据存储为临时数据,浏览器重定向。

2.2 创建 Razor Pages 来处理表单

  同样的模式可以使用 Razor Pages 实现。需要一个页面来呈现和处理表单数据,另一个页面显示结果。给 Pages 文件夹添加一个名为 FormHandler.cshtml 的 Razor Pages。

@page "/pages/form/{id:long?}"
@model FormHandlerModel
@using Microsoft.AspNetCore.Mvc.RazorPages

<div class="m-2">
    <h5 class="bg-primary text-white text-center p-2">HTML Form</h5>
    <form asp-page="FormHandler" method="post">
        <div class="form-group">
            <label>Name</label>
            <input class="form-control" name="Name" value="@Model.Product.Name" />
        </div>
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>
</div>

@functions
{

    [IgnoreAntiforgeryToken]
    public class FormHandlerModel : PageModel
    {
        private DataContext context;

        public FormHandlerModel(DataContext dbContext)
        {
            context = dbContext;
        }

        public Product Product { get; set; }

        public async Task OnGetAsync(long id = 1)
        {
            Product = await context.Products.FindAsync(id);
        }

        public IActionResult OnPost()
        {
            foreach (string key in
                Request.Form.Keys.Where(k => !k.StartsWith("_")))
            {
                TempData[key] = string.Join(", ", Request.Form[key]);
            }
            return RedirectToPage("FormResults");
        }
    }
}

  OnGetAsync 处理程序方法从数据库中检索 Product,视图使用该产品设置 HTML 表单中输入元素的值。该表单配置为发送一个将由 OnPost 处理程序方法处理的 HTTP POST 请求。表单数摊存储为临时数据,并向浏览器发送一个到 FormResults 表单的重定向。
  要创建浏览器将被重定到的页面,向 Pages 文件夹添加一个名为 FormResults.cshtml 的 Razor Pages。

@page "/pages/results"

<div class="m-2">
    <table class="table table-striped table-bordered table-sm">
        <thead>
            <tr class="bg-primary text-white text-center">
                <th colspan="2">Form Data</th>
            </tr>
        </thead>
        <tbody>
            @foreach (string key in TempData.Keys)
            {
                <tr>
                    <th>@key</th>
                    <td>@TempData[key]</td>
                </tr>
            }
        </tbody>
    </table>
    <a class="btn btn-primary" asp-page="FormHandler">Return</a>
</div>

  使用浏览器导航到 http:/localhost:5000/pages/form,在文本字段中输入一个值,然后单击 Submit 按钮。表单数据由 OnPost 方法处理,浏览器重定向到 /pages/results,从而显示表单数据。

3 使用标签助手改进HTML表单

  上面示例展示了处理 HTML 表单的基本机制,但是 ASP.NET Core 包含转换表单元素的标签助手。接下来描述标签助手并演示它们的用法。

3.1 使用表单元素

  FormTagHelper 类是表单元素的内置标签助手类,用于管理 HTML 表单的配置,以便它们能够针对正确的操作或页面处理程序,而不需要硬编码 URL。
表单元素的内置标签助手属性:

名称 描述
asp-controller 此属性用于为操作属性 URL 指定路由系统的 controller 值。如果省略,那么使用呈现视图的控制器
asp-action 此属性用于为 action属性 URL,的路由系统指定 action 值的操作方法。如果省略,就使用呈现视图的操作
asp-page 此属性用于指定 Razor Pages 的名称
asp-page-handler 此属性用于指定处理程序方法的名称,该处理程序方法用于处理请求。
asp-route-* 名称以 asp-route 开头的属性用于为操作属性 URL 指定附加值,以便使用 asp-route-id 属性为路由系统提供 id 段的值
asp-route 此属性指定将用于为操作生成 URL 属性的路由名称
asp-antiforgery 这个属性控制是否将防伪信息添加到视图中
asp-fragmen 此属性为生成的 URL 指定一个片段

设置表单目标
  asp-action 属性用于指定将接收 HTTP 请求的操作的名称。修改在Views/Form 文件夹的 Form.cshtml 视图,以应用标签助手。

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

  asp-page 属性用于选择 Razor Pages 作为表单的目标。 在 Pages 文件夹的 FormHandler.cshtm 文件中设置表单目标。

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

3.2 改变表单按钮

  发送表单的按钮可以在表单元素之外定义。在这些情况下,按钮具有一个 form 属性,该属性的值对应于它所关联的表单元素的 id 属性,以及一个表单 action 属性,该属性指定表单的目标URL。

<form asp-action="submitform" method="post" id="htmlform">
    <div class="form-group">
        <label>Name</label>
        <input class="form-control" name="Name" value="@Model.Name" />
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
</form>
<button form="htmlform" asp-action="submitform" class="btn btn-primary mt-2">
    Sumit(Outside Form)
</button>

  添加到表单元素的 id 属性的值被按钮用作 form 属性的值,它告诉浏览器,在单击按钮时提交哪个表单。
也可用于 Razor Pages。

<form asp-page="FormHandler" method="post" id="htmlform">
    <div class="form-group">
        <label>Name</label>
        <input class="form-control" name="Name" value="@Model.Product.Name" />
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
</form>
<button form="htmlform" asp-page="FormHandler" class="btn btn-primary mt-2">
    Sumit(Outside Form)
</button>

  使用浏览器请求 http://localhost:5000/controllers/formhttp://localhost:5000/pages/form

4 处理 input 元素

  input 元素是 HTML 表单的主干,InputTagHelper 类用于转换 input 元素,以下属性反映它们要收集的视图模型属性的数据类型和格式。
  input 元素的内置标签助手属性:

名称 描述
asp-for 这个属性用于指定 input 元素所表示的视图模型属性
asp-format 这个属性用于指定 input 元素所表示的视图模型属性的值的格式

  asp-for 属性设置为视图模型属性的名称,然后用于设置 input 元素的 name、id、type 和 value属性。在Views/Form 文件夹的 Form.cshtml 文件使用。

<label>Name</label>
@*<input class="form-control" name="Name" value="@Model.Name" />*@
<input class="form-control" asp-for="Name" />

  这个标签助手使用一个模型表达式,这就是为什么在指定 asp-for 属性的值时不使用@字符。如果査看在使用浏览器请求 http:/localhost:5000/controllers/form 时应用程序返回的 HTML,可看到标签助手将 input 元素转换为如下形式:

<input class="form-control" type="text" id="Name" name="Name" value="Kayak">

  id 和 name 属性的值是通过模型表达式获得的,从而确保在创建表单时不会引入拼写错误。

4.1 转换 input 元素的类型属性

  input 元素的 type 属性告诉浏览器如何显示元素,以及它应该如何限制用户输入的值。input 元素默认配置是 text 类型,没有任何输入限制。下面在 Views/Form 文件夹的 Form.cshtml 中 type 属性使用 number 类型。

<div class="form-group">
    <label>Id</label>
    <input class="form-control" asp-for="ProductId" />
</div>

  新元素使用 asp-for 属性来选择视图模型的 Productld 属性。使用浏览器请求http://localhost:5000/controllers/form,查看标签助手转换的元素如下。

<input class="form-control" type="number" data-val="true" 
    data-val-required="The ProductId field is required." 
    id="ProductId" name="ProductId" value="1">

  type 属性的值由 asp-for 属性指定的视图模型属性的类型决定。ProductId属性的类型是 C# long类型,它导致标签助手将 input 元素的 type 属性设置为 number,这将限制元素使其只接收数字字符。data-val 和 data-val 所需的属性添加到 input 元素中帮助验证。也可以通过显式地定义 input 元素上的 type 属性可覆盖默认。

4.2 格式化 input 元素值

  当 action 方法为视图提供视图模型对象时,标签助手使用 asp-for 属性值来设置 input 元素的 value 属性。asp-format 属性用于指定数据值的格式。修改Form.cshtml。

<div class="form-group">
    <label>Price</label>
    <input class="form-control" asp-for="Price" asp-format="{0:#,###.00}"/>
</div>

通过模型类应用格式化
  如果总是希望对模型属性使用相同的格式,就可以使用 DisplayFommat 属性来装饰 C#类属性在 using System.ComponentModel.DataAnnotations名称空间中定义。Displayformat 属性需要两个数来格式化数据值:DisplayFormat 参数指定格式化字符串,将 ApplyformatnEdiMode设量为 true 意味着将值应用于编辑的元素(包括jmput 元素)时应该使用格式化。
  在 Models 文件夹的 Product.cs 文件中应用格式化属性。

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

  asp-format 属性优先于 DisplayFormat 属性,因此从视图中删除该属性。并使用浏览器请求 http://localhost:5000/controllers/Form/index/5,会看到由属性定义的格式化字符串已经应用。

4.3 在 input 元素中显示相关数据的值

  在使用 Entity Framework Core 时,经常需要显示从相关数据中获得的数据值,使用 asp-for 属性很容易做到这一点,因为模型表达式允许选择嵌套的导航属性。
  在 Controllers 文件夹的 FormController.cs 文件中包含相关数据。

public async Task<IActionResult> Index(long id = 1)
{
    var result = await context.Products.Include(p => p.Category)
        .Include(p => p.Supplier).FirstAsync(p => p.ProductId == id);
    return View("Form", result);
}

  在Views/Form 文件夹的 Form.cshtml 文件中显示相关数据。

<div class="form-group">
    <label>Category</label>
    <input class="form-control" asp-for="Category.Name" />
</div>
<div class="form-group">
    <label>Supplier</label>
    <input class="form-control" asp-for="Supplier.Name" />
</div>

  asp-for 属性的值是相对于视图模型对象表示的,可以包含嵌套属性,允许选择EntityFramework Core 分配给 Category 和 Supplier 导航属性的相关对象的 Name 属性。Razor Pages 使用了相同的技术,只是属性是相对于页面模型对象表示的。

<div class="form-group">
    <label>Name</label>
    <input class="form-control" asp-for="Product.Name" />
</div>
<div class="form-group">
    <label>Price</label>
    <input class="form-control" asp-for="Product.Price" />
</div>
<div class="form-group">
    <label>Category</label>
    <input class="form-control" asp-for="Product.Category.Name" />
</div>
<div class="form-group">
    <label>Supplier</label>
    <input class="form-control" asp-for="Product.Supplier.Name" />
</div>

......

public async Task OnGetAsync(long id = 1)
{
    Product = await context.Products.Include(p => p.Category)
    .Include(p => p.Supplier).FirstAsync(p => p.ProductId == id);
}

  使对控制器的更改生效,并使用浏览器请求 http://localhost:5000/controllers/form/index/5,和http://localhost:5000/pages/form

5 使用 label 元素

  LabelTagHelper 类用于转换 label 元素,因此 for 属性的设置与用于转换 input 元素的方法一致。
  标签助手设置 label 元素的内容,以便它包含所选视图模型属性的名称。标签助手设置 for 属性,该属性表示与特定 input 元素的关联,并在单击关联的标签时使 input 元素获得焦点。
  在 Views/Fomm 文件夹的 Form.cshtml 中,将 asp-for 属性应用于表单视图,以将每个 label 元素与表示相同视图模型属性的 imput 元素相关联。

<div class="form-group">
    <label asp-for="ProductId"></label>
    <input class="form-control" asp-for="ProductId" />
</div>
<div class="form-group">
    <label asp-for="Name"></label>
    <input class="form-control" asp-for="Name" />
</div>
<div class="form-group">
    <label asp-for="Price"></label>
    <input class="form-control" asp-for="Price" />
</div>
<div class="form-group">
    <label asp-for="Category.Name">Category</label>
    <input class="form-control" asp-for="Category.Name" />
</div>
<div class="form-group">
    <label asp-for="Supplier.Name">Supplier</label>
    <input class="form-control" asp-for="Supplier.Name" />
</div>

6 使用 select 和 option 元素

  select 和 option 元素用于向用户提供一组固定的选择。
  SelectTagHelper 负责转换 select 元素,并支持以下描述的属性。

名称 描述
asp-for 此属性用于指定 select 元素所表示的视图或页面模型属性
asp-items 此属性用于为 select 元素中包含的 option 元素指定值源

  在 Views/Form 文件夹的 Form.cshtml 中用 select 元素替换了类别的 input 元素。

<div class="form-group">
    <label asp-for="Category.Name">Category</label>
    <select class="form-control" asp-for="CategoryId">
        <option value="1">Watersports</option>
        <option value="2">Soccer</option>
        <option value="3">Chess</option>
    </select>
</div>

  所选的属性添加到 option 元素中,与视图模型的 CategoryId 值相对应。

<option value="2" selected="selected">Soccer</option>

  选择 option 元素的任务是由 OptionTagHelper 类执行的,该类通过 TagHelperContext. Items 集合接收来自 SelectTagHelper 的指令,结果是 select 元素显示与 Product 对象的 CategoryId 值相关联的类别名称。
填充 select 元素
  asp-items 属性用于为标签助手提供 SelectListltem 对象的列表序列,为这些对象生成 option元素。在 Controllers 文件夹的 FormController.cs 的 Index方法, 修改表单控制器的索引操作,以通过视图包向视图提供一系列 SelectListltem 对象。

ViewBag.Categories = new SelectList(context.Categories, "CategoryId", "Name");

  可直接创建 SelectListltem 对象,但是 ASP.NET Core 提供了 SelectList 类来适应现有的数据序列。在本例中,从数据库中获得的 Category 对象序列传递给 SelectList 构造函数,还传递了应该用作 option 元素的值和标签的属性名称。在 Views/Form 文件夹的 Form.cshtml 中,更新了 form 视图以使用 SelectList。

<select class="form-control" asp-for="CategoryId" asp-items="@ViewBag.Categories">
</select>

7 处理文本区域

  textarea 元素用于从用户那里请求大量文本,TextAreaTagHelper 负贵转换 textarea 元素。
  TextAreaTagHelper 相对简单,为 asp-for 属性提供的值用于设置 textarea 元素上的 id 和 name属性。asp-for属性选择的属性值用作textarea元素的内容。在 Vews/Fomm 文件夹的 Form.cshtm 替换了Supplier.Name属性的输入元素,带有已应用 asp-for 属性的文本区域。

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

标签:Core,ASP,Form,10,元素,视图,表单,asp,属性
From: https://www.cnblogs.com/nullcodeworld/p/18246657

相关文章

  • 6.10
    packagecom.example.spring2.mapper;importcom.example.spring2.entity.User;importorg.apache.ibatis.annotations.Insert;importorg.apache.ibatis.annotations.Mapper;importorg.apache.ibatis.annotations.Param;importorg.apache.ibatis.annotations.Select;import......
  • 5.10
    <?xmlversion="1.0"encoding="utf-8"?><ScrollViewxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.androi......
  • usoclient命令 参数 是一个用于管理 Windows Update 的命令行工具,可以在 Windows 10
    usoclient是一个用于管理WindowsUpdate的命令行工具,可以在Windows10和WindowsServer操作系统中使用。它提供了一种在命令行界面下执行Windows更新任务的方法,从而允许管理员和技术支持人员以更灵活和自动化的方式处理更新。为什么使用 usoclient 命令?自动化更新......
  • 中兴ZXV10 B863AV3.1-M2 线刷教程教学ROM下载
     中兴ZXV10B863AV3.1-M2线刷教程教学ROM下载 适用于:B863AV3.1-M2默认盒子桌面简洁纯净版,安卓9,网线版和WIFI版功能,下载后解压刷机包USB_Burning_Tool线刷,需要短接器和双公头usb线使用的是盒子桌面,多主题应用市场,有软件推送,栅格主题,win主题,简洁主题,教育主题,可上锁,自由......
  • 跟着杨中科学习(六)EFCore(四)
    自引用的组织结构树classOrgUnit{publiclongId{get;set;}publiclong?ParentId{get;set;}publicstringName{get;set;}publicOrgUnit?Parent{get;set;}publicList<OrgUnit>Children{get;set;}=newList<OrgUnit&g......
  • nginx编译安装-麒麟v10Arm64
    环境信息操作系统:KylinLinuxAdvancedServerV10(Lance)架构:Armkeepalived版本:2.3.1编译安装依赖包yuminstallgccgcc-c++makeunzippcrepcre-develzlibzlib-devellibxml2libxml2-develreadlinereadline-develncursesncurses-develperl-develperl-ExtU......
  • keepalived编译安装-麒麟v10Arm64
    环境信息操作系统:KylinLinuxAdvancedServerV10(Lance)架构:Armkeepalived版本:2.3.1编译wgethttps://www.keepalived.org/software/keepalived-2.3.1.tar.gztarxvfkeepalived-2.3.1.tar.gzcdkeepalived-2.3.1/./configure--prefix=/usr/local/keepalivedmake......
  • CIFAR-100 dataset分类
    ThisdatasetisjustliketheCIFAR-10,exceptithas100classescontaining600imageseach.Thereare500trainingimagesand100testingimagesperclass.The100classesintheCIFAR-100aregroupedinto20superclasses.Eachimagecomeswitha"......
  • 2024.6.10
    01背包问题详解01背包是一种动态规划问题。动态规划的核心就是状态转移方程,本文主要解释01背包状态转移方程的原理。问题描述01背包问题可描述为如下问题:有一个容量为V的背包,还有n个物体。现在忽略物体实际几何形状,我们认为只要背包的剩余容量大于等于物体体积,那就可以装进背包里......
  • P10432 [JOISC 2024 Day1] 滑雪 2
    MyBlogsP10432[JOISC2024Day1]滑雪2感觉是挺好的观察性质题,vp的时候场切了。首先酒店一定是建在最低的某一个点。把高度离散化之后,把点扔到对应的位置。可以发现高度为\(i\)的层的所有点,如果能接上一层的连接器那一定会尽量接上(因为到了下一层它本身也可以贡献一个空......