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