ASP.NET Core Razor Pages 教程六 处理表单

处理表单

任何成功的电子商务网站都需要能够处理订单。如果你没有客户的联系方式和送货地址就很难做到这一点。网站收集这类信息的方式是使用表单。

在本节中,你将向 Order 页面添加一个表单,同时还将向表单中添加验证,以确保信息的收集是有效和完整的。

准备工作

首先,添加以下的样式声明到 wwwroot/css 中的 site.css 文件:

label[for="OrderQuantity"]{
  padding-left: 15px;
}

#OrderQuantity{
  margin: 0 15px;
  max-width: 100px;
}

.order-calc{
  display: inline-block;
  margin: 0 10px;
}

.input-validation-error, .input-validation-error:focus {
  background: #ffccba;
  color: #d63301;
}

.form-control.input-validation-error:focus{
  border-color: #d63301;
  box-shadow: 0 0 0 0.2rem rgba(255, 123, 123, 0.5);
}

.field-validation-error {
  color: #be3e16;
}

.validation-summary-errors {
  color: #be3e16;
}

前三种风格纯粹是装饰性的。最后四种样式将有助于轻松地识别字段验证错误的位置。现在,将以下突出显示的行添加到 Order.cshtml.cs 文件中:

using System;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Bakery.Data;
using Bakery.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace Bakery.Pages
{
    public class OrderModel : PageModel
    {
        private BakeryContext db;

        public OrderModel(BakeryContext db) => this.db = db;

        [BindProperty(SupportsGet =true)]
        public int Id { get; set; }
        public Product Product { get; set;}
        [BindProperty, EmailAddress, Required, Display(Name="Your Email Address")]
        public string OrderEmail { get; set; }
        [BindProperty, Required(ErrorMessage="Please supply a shipping address"), Display(Name="Shipping Address")]
        public string OrderShipping { get; set; }
        [BindProperty, Display(Name="Quantity")]
        public int OrderQuantity { get; set; } = 1;

        public async Task OnGetAsync() => Product = await db.Products.FindAsync(Id);
    }
}

额外的 using 指令使用 DataAnnotations 命名空间。这个命名空间包含许多的属性,其中一些属性用于装饰已添加到 PageModel 的属性。OrderEmail 属性应用了 DataAnnotation 属性(以及 BindProperty属性):

  • EmailAddress - 电子邮件地址-它验证字符串是否与电子邮件地址的模式匹配
  • Required - 指定的值是必需的
  • Display - 允许您自定义属性在 UI 中使用的值

其中两个属性在验证中发挥作用,稍后你就可以看到了。OrderQuantity 属性分配的默认值为 1

添加表单

在 Order.cshtml 的底部添加以下几行:

<form method="post">
    <div class="row">
        <div class="col-3">
            <img src="~/Images/Products/Thumbnails/@Model.Product.ImageName" class="img-fluid img-thumbnail" alt="Image of @Model.Product.Name"/>
        </div>
        <div class="col-9">
            <ul class="orderPageList" data-role="listview">
                <li>
                    <div>
                        <p class="description">@Model.Product.Description</p>
                    </div>
                </li>
                <li class="email">
                    <div class="form-group">
                        <label asp-for="OrderEmail"></label>
                        <input asp-for="OrderEmail" class="form-control form-control-sm" />
                        <span asp-validation-for="OrderEmail"></span>
                    </div>
                </li>
                <li class="shipping">
                    <div class="form-group">
                        <label asp-for="OrderShipping"></label>
                        <textarea rows="4" asp-for="OrderShipping" class="form-control form-control-sm"></textarea>
                        <span asp-validation-for="OrderShipping"></span>
                    </div>
                </li>
                <li class="quantity">
                    <div class="form-group row">
                        <label asp-for="OrderQuantity" class="col-1 col-form-label"></label>
                        <input asp-for="OrderQuantity" class="form-control form-control-sm"/>
                        x
                        <span class="order-calc" id="orderPrice">@Model.Product.Price.ToString("f")</span>
                        =
                        <span class="order-calc" id="orderTotal">@Model.Product.Price.ToString("f")</span>
                        <span asp-validation-for="OrderQuantity"></span>
                    </div>
                </li>
            </ul>
            <p class="actions">
                <input type="hidden" asp-for="Product.Id" />
                <button class="btn btn-danger order-button">Place Order</button>
            </p>
        </div>
    </div>
</form>

@section scripts{
<script type="text/javascript">
    $(function () {
        var price = parseFloat($("#orderPrice").text()).toFixed(2),
            total = $("#orderTotal"),
            orderQty = $("#OrderQuantity");

        orderQty.on(‘change‘, function () {
            var quantity = parseInt(orderQty.val());
            if (!quantity || quantity < 1) {
                orderQty.val(1);
                quantity = 1;
            } else if (quantity.toString() !== orderQty.val()) {
                orderQty.val(quantity);
            }
            total.text("$" + (price * quantity).toFixed(2));
        });
    });
</script>
}

表单使用标记帮助器来呈现标签,输入和验证消息。 目标输入元素的标记助手特别强大。 PageModel 属性传递给输入标记助手上的 asp-for 属性。 然后,输入标记帮助程序根据属性呈现正确的 name 属性,以便模型绑定可以无缝地工作。 分配给属性的任何值都将分配给输入。 输入的 type 属性是根据属性的数据类型生成的。

表单本身也将由标记帮助器作为目标,它将确保呈现请求验证令牌。

代码以JavaScript块结尾,根据订购的商品数量计算总价。 <script> 标记放在名为 scripts@section 块中,该块被小心地放置在布局页面中,以便在其他站点范围的脚本(包括脚本块所依赖的 jQuery)下面呈现其内容。

接下来,您需要一个处理程序方法来处理表单。将以下内容添加到 Order.cshtml.cs 文件中:

public async Task<IActionResult> OnPostAsync()
{
    Product = await db.Products.FindAsync(Id);
    if(ModelState.IsValid){
        return RedirectToPage("OrderSuccess");
    }
    return Page();
}

目前,这个方法所做的只是检查 ModelState.IsValid。 这确保模型绑定特性得到满足, 所有提交的值都通过验证检查, 并且所有需要的值都存在。 如果验证中有任何错误, 则向 ModelState 对象添加条目,并重新显示当前页面(return page())。 如果提交是有效的, 用户将被重定向到 OrderSuccess 页面, 接下来您将添加该页面。

此模式称为 Post-Redirect-Get(PRG),旨在最大程度地减少双重发布导致重复提交的可能性。

如果表单中存在错误,则会再次显示该页面,验证标记帮助程序将显示验证错误的详细信息。

现在使用以下命令将 OrderSuccess 页面添加到应用程序:

dotnet new page --name OrderSuccess --output Pages --namespace Bakery.Pages

使用以下的代码来替换 OrderSuccess.cshtml 文件的内容:

@page
@model Bakery.Pages.OrderSuccessModel
@{
}
<ol id="orderProcess">
    <li><span class="step-number">1</span>Choose Item</li>
    <li><span class="step-number">2</span>Details &amp; Submit</li>
    <li class="current"><span class="step-number">3</span>Receipt</li>
</ol>
<h1>Order Confirmation</h1>

现在是测试表单是否正常工作和处理的时候了。输入 dotnet run 启动应用程序,然后导航到 https://localhost:5001。选择 Lemon Tart 产品,并确保表单显示正确:

现在,在不输入电子邮件或送货地址的情况下按下 Place Order 按钮, 这样您就可以测试验证了。 两个字段都应该变成粉红色,错误消息应该出现在它们下面:

您可以执行进一步的测试,比如删除 Quantity 框中的值, 或者在电子邮件输入中输入一个随机字符串。 每次提交表单后, 错误消息都会出现。

添加客户端验证

此时,所有验证都在服务器上执行。表单被发布,整个页面被重新呈现以向用户提供反馈。在开发站点时,您并不会真正注意到这种往返,因为客户机和服务器在同一台机器上。然而,在实际应用程序中,在用户收到任何反馈之前可能会有一些延迟。在客户端验证将为用户提供即时反馈。

在客户机上验证应该只被看作是对用户的一种礼貌。它永远不应该取代服务器端验证。对于具有少量 HTML/JavaScript 知识的人来说,绕过客户端验证是非常容易的。

Razor Pages 默认包含客户端验证(Client side validation),但需要启用它。 您可以通过在页面中包含 jQuery Validation 和 jQuery Unobtrusive Validation 库来实现。 包含这些脚本的代码已在名为 _ValidationScriptsPartial.cshtml 的部分中提供,该部分位于 Pages/Shared 文件夹中。 要包含它,只需将部分标记助手添加到 Order.cshtml 中的脚本部分,如下面突出显示的代码行所示:

@section scripts{
<partial name="_ValidationScriptsPartial"></partial>
<script type="text/javascript">
    $(function () {
        var price = parseFloat($("#orderPrice").text()).toFixed(2),
            total = $("#orderTotal"),
            orderQty = $("#OrderQuantity");

        orderQty.on(‘change‘, function () {
            var quantity = parseInt(orderQty.val());
            if (!quantity || quantity < 1) {
                orderQty.val(1);
                quantity = 1;
            } else if (quantity.toString() !== orderQty.val()) {
                orderQty.val(quantity);
            }
            total.text("$" + (price * quantity).toFixed(2));
        });
    });
</script>
}

现在,如果您尝试提交缺少值的表单,则会显示错误,而不会将表单实际发布到服务器。 如果您提供满足验证的值,您应该进入 OrderSuccess 页面:

接要

在本节中,您已经使用标记助手创建了一个表单,并添加了服务器端和客户端验证。您已经成功地测试了表单。到目前为止,您还没有对发布的值做任何有意义的事情。在下一节中,您将使用已发布的值来构造电子邮件并发送它。

原文地址:https://www.cnblogs.com/mahidol/p/10424071.html

时间: 2024-10-08 12:54:37

ASP.NET Core Razor Pages 教程六 处理表单的相关文章

ASP.NET Core Razor Pages 教程五 使用数据

使用数据 第一次使用数据时,你将重点关注于使用 BakeryContext 检索要在主页和订购页上显示的数据, 这些数据还没有添加到应用程序中. 提醒一下,主页应该类似于此处的 ASP.NET Web Pages 版本: 所有产品的描述.图片和价格一起显示,随机选择其中一个产品作为特色产品出现在页面的顶部. 管理数据的显示需要少量的准备工作.首先,将以下代码添加到位于 wwwroot/css 中的现有 site.css 文件中: body{ color: #696969; } a:link {

Laravel教程 六:表单 Forms

Laravel教程 六:表单 Forms 此文章为原创文章,未经同意,禁止转载. Form laravel 5.2 之后请使用 laravelcollective/html 替换 illuminate/html. 出现问题先看评论. 在开始之前,我们把界面先美化一点点先: 首先到https://github.com/JellyBool/blog-css-js得到静态文件,然后分别修改下面三个文件: 1. app.blade.php 2. articles/index.blade.php 3. a

Laravel 5系列教程六:表单 Forms

免费视频教程地址https://laravist.com/series/laravel-5-basic 在开始之前,我们把界面先美化一点点先: 首先到https://github.com/JellyBool/blog-css-js得到静态文件,然后分别修改下面三个文件: 1. app.blade.php 2. articles/index.blade.php 3. articles/show.blade.php 下面的视图代码的修改部分,如果你偷懒,你可以使用ctrl+c大法. 在app.bla

学习ASP.NET Core Razor 编程系列九——增加查询功能

学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET Core Razor 编程系列三——创建数据表及创建项目基本页面 学习ASP.NET Core Razor 编程系列四——Asp.Net Core Razor列表模板页面 学习ASP.NET Core Razor 编程系列五——Asp.Net Core Razor新建模板页面 学习ASP.NET C

学习ASP.NET Core Razor 编程系列七——修改列表页面

学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET Core Razor 编程系列三——创建数据表及创建项目基本页面 学习ASP.NET Core Razor 编程系列四——Asp.Net Core Razor列表模板页面 学习ASP.NET Core Razor 编程系列五——Asp.Net Core Razor新建模板页面 学习ASP.NET C

学习ASP.NET Core Razor 编程系列十——添加新字段

学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET Core Razor 编程系列三——创建数据表及创建项目基本页面 学习ASP.NET Core Razor 编程系列四——Asp.Net Core Razor列表模板页面 学习ASP.NET Core Razor 编程系列五——Asp.Net Core Razor新建模板页面 学习ASP.NET C

.NET Core Razor Pages中ajax get和post的使用

ASP.NET Core Razor Pages Web项目大部分情况下使用继承与PageModel中的方法直接调用就可以(asp-page),但是有些时候需要使用ajax调用,更方便些.那么如何使用ajax调用呢?? 1.Razor Pages普通页面的跳转 <a asp-page="About">About</a> <form asp-page="./Index" method="get"> <div

学习ASP.NET Core Razor 编程系列五——Asp.Net Core Razor新建模板页面

学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET Core Razor 编程系列三——创建数据表及创建项目基本页面 学习ASP.NET Core Razor 编程系列四——Asp.Net Core Razor列表模板页面 上一篇文章中我们学习了列表页面的结构,@page与@model两个关键Razor指令,以及页面布局应该修改哪里.这一篇文章我们来

观看杨老师(杨旭)Asp.Net Core MVC入门教程记录

观看杨老师(杨旭)Asp.Net Core MVC入门教程记录 ASP.NET Core MVC入门 Asp.Net Core启动和配置 Program类,Main方法 Startup类 依赖注入,IoC容器 生命周期 Transient:每次被请求都会创建新的实例 Scoped:每次Web请求会创建一个实例 Singleton:一旦被创建实例,就会一直使用这个实例,直到应用停止 依赖注入好处 不用去管生命周期 类型之间没有依赖 补充: ILogger:在Microsoft.Extensions