zoukankan      html  css  js  c++  java
  • ASP.NET Core Razor Pages 教程六 处理表单

    处理表单

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

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

    准备工作

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

    label[for="OrderQuantity"]{
      padding-left: 15px;
    }
    
    #OrderQuantity{
      margin: 0 15px;
      max- 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 产品,并确保表单显示正确:
    Lemon Tart

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

    您可以执行进一步的测试,比如删除 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 页面:
    orderSuccess

    接要

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

  • 相关阅读:
    图片剪切
    js事件(Event)知识整理
    原生JavaScript事件详解
    underscore源码解析
    win7 vi工具
    开源java数据库库
    win7快捷键
    win7 绿色版MySQL安装与配置
    maven jetty
    javax inect
  • 原文地址:https://www.cnblogs.com/mahidol/p/10424071.html
Copyright © 2011-2022 走看看