处理表单
任何成功的电子商务网站都需要能够处理订单。如果你没有客户的联系方式和送货地址就很难做到这一点。网站收集这类信息的方式是使用表单。
在本节中,你将向 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 & 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 页面:
接要
在本节中,您已经使用标记助手创建了一个表单,并添加了服务器端和客户端验证。您已经成功地测试了表单。到目前为止,您还没有对发布的值做任何有意义的事情。在下一节中,您将使用已发布的值来构造电子邮件并发送它。
ASP.NET Core Razor Pages 教程六 处理表单
原文地址:https://www.cnblogs.com/mahidol/p/10424071.html