• 创建基于ASP.NET core 3.1 的RazorPagesMovie项目(三)-已搭建基架的Razor页面解释和更新


    本节主要介绍在上一节中通过搭建基架而创建的Razor页面,并做一些UI改变。

    一、创建、删除、详细信息和编辑页面

      1、双击Pages/Movies/Index.cshtml.cs文件,这是一个Razor页面模型:

      

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Threading.Tasks;
     5 using Microsoft.AspNetCore.Mvc;
     6 using Microsoft.AspNetCore.Mvc.RazorPages;
     7 using Microsoft.EntityFrameworkCore;
     8 using RazorPagesMovie.Data;
     9 using RazorPagesMovie.Models;
    10 
    11 namespace RazorPagesMovie
    12 {
    13     public class IndexModel : PageModel
    14     {
    15         private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
    16 
    17         public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
    18         {
    19             _context = context;
    20         }
    21 
    22         public IList<Movie> Movie { get;set; }
    23 
    24         public async Task OnGetAsync()
    25         {
    26             Movie = await _context.Movie.ToListAsync();
    27         }
    28     }
    29 }

      ① 第13行:表示该Razor页面派生自PageModel。约定:PageModel派生的类称为<PageName>Model。

      ② 第17行:表示这是一个构造函数,使用依赖关系注入将RazorPagesMovieContent添加到页。所有已搭建基架的页面都遵循这个模式。

      ③ 第24行:表示对页面发出请求时,OnGetAsync方法向Razor页面返回影片列表。调用OnGetAsync或OnGet以初始化页面的状态。OnGetAsync方法将获得的影片列表显示出来。当OnGet返回void或OnGetAsync返回task时,使用任何返回语句。因为此时返回的Movie对象,在程序中做了定义(第22行)

     2、双击Pages/Movies/Create.cshtml.cs文件,这也是一个Razor页面模型:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Threading.Tasks;
     5 using Microsoft.AspNetCore.Mvc;
     6 using Microsoft.AspNetCore.Mvc.RazorPages;
     7 using Microsoft.AspNetCore.Mvc.Rendering;
     8 using RazorPagesMovie.Data;
     9 using RazorPagesMovie.Models;
    10 
    11 namespace RazorPagesMovie
    12 {
    13     public class CreateModel : PageModel
    14     {
    15         private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
    16 
    17         public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
    18         {
    19             _context = context;
    20         }
    21 
    22         public IActionResult OnGet()
    23         {
    24             return Page();
    25         }
    26 
    27         [BindProperty]
    28         public Movie Movie { get; set; }
    29 
    30         // To protect from overposting attacks, please enable the specific properties you want to bind to, for
    31         // more details see https://aka.ms/RazorPagesCRUD.
    32         public async Task<IActionResult> OnPostAsync()
    33         {
    34             if (!ModelState.IsValid)
    35             {
    36                 return Page();
    37             }
    38 
    39             _context.Movie.Add(Movie);
    40             await _context.SaveChangesAsync();
    41 
    42             return RedirectToPage("./Index");
    43         }
    44     }
    45 }

      ④ 第32、22行:当返回类型是IActionResult或Task<IActionResult>时,必须提供返回语句。

       3、双击Pages/Movies/Index.cshtml文件,这是一个Razor页面:

     1 @page
     2 @model RazorPagesMovie.IndexModel
     3 
     4 @{
     5     ViewData["Title"] = "Index";
     6 }
     7 
     8 <h1>Index</h1>
     9 
    10 <p>
    11     <a asp-page="Create">Create New</a>
    12 </p>
    13 <table class="table">
    14     <thead>
    15         <tr>
    16             <th>
    17                 @Html.DisplayNameFor(model => model.Movie[0].Title)
    18             </th>
    19             <th>
    20                 @Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
    21             </th>
    22             <th>
    23                 @Html.DisplayNameFor(model => model.Movie[0].Genre)
    24             </th>
    25             <th>
    26                 @Html.DisplayNameFor(model => model.Movie[0].Price)
    27             </th>
    28             <th></th>
    29         </tr>
    30     </thead>
    31     <tbody>
    32 @foreach (var item in Model.Movie) {
    33         <tr>
    34             <td>
    35                 @Html.DisplayFor(modelItem => item.Title)
    36             </td>
    37             <td>
    38                 @Html.DisplayFor(modelItem => item.ReleaseDate)
    39             </td>
    40             <td>
    41                 @Html.DisplayFor(modelItem => item.Genre)
    42             </td>
    43             <td>
    44                 @Html.DisplayFor(modelItem => item.Price)
    45             </td>
    46             <td>
    47                 <a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
    48                 <a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
    49                 <a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
    50             </td>
    51         </tr>
    52 }
    53     </tbody>
    54 </table>

      Razor可以从HTML转换为C#或Razor特定的标记。当@符号后面跟着Razor保留关键字时,它会转换为Razor特定标记,否则会转换为C#。

      ① 第1行:@page指令,它是一个Razor指令的一个示例。该指令表示将文件转换为一个MVC操作。这意味着它可以处理请求。@page必须是页面上第一个Razor指令。

      ② 第17-26行:@Html 这是一系列的使用Lambda表达式的HTML帮助程序。DisplayNameFor HTML帮助程序检查Lambda表达式引用的Tile、ReleaseDate等属性来确定显示名称。检查Lambda表达式(而非求值),意味着model、model.Movie或model.Movie[0]为null或空时,不会存在任何访问冲突。

      ③ 第35-44行:@Html.DisplayFor是对Lambda表达式进行求值,将获得该模型的属性值。

      ④ 第2行:@model指令,指定传递给Razor页面的模型类型。这个例子中的模型类型,就是第1段中派生于PageModel类的IndexModel模型。

      ⑤ 第4-6行:@符号后面没有Razor关键字,表示这是C#的一个示例。{}大括号中是C#代码块。这个页面的引用的模型是IndexModel,它派生于PageModel,PageModel基类中包含ViewData字典属性,可用于将数据传递到某个视图。我们可以采用键值对的模式将对象添加到ViewData字典中。这里,“Title”属性被添加到ViewData字典中。而“Title”属性又被用于/Pages/Shared/_Layout.cshtml文件中。见第4节中的第③条注释。

       4、双击/Pages/Shared/_Layout.cshtml文件

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="utf-8" />
     5     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     6     <title>@ViewData["Title"] - RazorPagesMovie</title>
     7     <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
     8     <link rel="stylesheet" href="~/css/site.css" />
     9 </head>
    10 <body>
    11     <header>
    12         <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
    13             <div class="container">
    14                 <a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
    15                 <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
    16                         aria-expanded="false" aria-label="Toggle navigation">
    17                     <span class="navbar-toggler-icon"></span>
    18                 </button>
    19                 <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
    20                     <ul class="navbar-nav flex-grow-1">
    21                         <li class="nav-item">
    22                             <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
    23                         </li>
    24                         <li class="nav-item">
    25                             <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
    26                         </li>
    27                     </ul>
    28                 </div>
    29             </div>
    30         </nav>
    31     </header>
    32     <div class="container">
    33         <main role="main" class="pb-3">
    34             @RenderBody()
    35         </main>
    36     </div>
    37 
    38     <footer class="border-top footer text-muted">
    39         <div class="container">
    40             &copy; 2019 - RazorPagesMovie - <a asp-area="" asp-page="/Privacy">Privacy</a>
    41         </div>
    42     </footer>
    43 
    44     <script src="~/lib/jquery/dist/jquery.min.js"></script>
    45     <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    46     <script src="~/js/site.js" asp-append-version="true"></script>
    47 
    48     @RenderSection("Scripts", required: false)
    49 </body>
    50 </html>

      ① 这是一个页面布局的模板(类似于母版页)。它允许HTML容器具有如下布局:在一个位置指定;应用于站点中的多个页面。

      ② 第34行:@RenderBody(),是显示全部页面专用视图的占位符。

      ③ 第6行:通过@ViewData["Title"]将字典中的对象“Title”的值取出来,和字符串‘- RazorPagesMovie’一起。最终形成页面上我们看到的标题:

      

       ④ Razor页面的注释方式采用:  @* 注释内容*@  的方式进行注释(区别于HTML的注释<!-- 注释-- >)。注释不会被发送到客户端

     5、更新布局

      ① 更改Title和链接页面

        /Pages/Shared/_Layout.cshtml文件:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - 电影</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" />
    </head>
    <body>
    <header>
    <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
    <div class="container">
    <a class="navbar-brand" asp-page="/Movies/Index">我的电影</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
    aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
    </button>

        这里一共更改了2处:

        <title>@ViewData["Title"] - 电影</title>   

        <a class="navbar-brand" asp-page="/Movies/Index">我的电影</a>

        其中第二处更改,原先的代码是:asp-area="" asp-page="/Movies/Index">,它表示一个标记帮助程序。更改之后,它是一个定位点标记帮助程序。asp-page="/Movies/Index"标记了帮助程序的属性和值可以创建指向/Movies/Index的Razor页面的连接。其中,asp-area属性值为空,表示连接中未使用区域。

      Pages/Movies/Index.cshtml文件:

    @page
    @model RazorPagesMovie.IndexModel

    @{
    ViewData["Title"] = "首页";
    }

    <h1>首页</h1>

      Pages/_ViewStart.cshtml中设置Layout属性:

    1 @{
    2     Layout = "_Layout";
    3 }

        这个标记,针对所有Razor文件将布局文件设置为Pages文件夹下的Pages/Shared/_Layout.cshtml。

      Pages/Movies/Create.cshtml.cs文件:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Threading.Tasks;
     5 using Microsoft.AspNetCore.Mvc;
     6 using Microsoft.AspNetCore.Mvc.RazorPages;
     7 using Microsoft.AspNetCore.Mvc.Rendering;
     8 using RazorPagesMovie.Data;
     9 using RazorPagesMovie.Models;
    10 
    11 namespace RazorPagesMovie
    12 {
    13     public class CreateModel : PageModel
    14     {
    15         private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
    16 
    17         public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
    18         {
    19             _context = context;
    20         }
    21 
    22         public IActionResult OnGet()
    23         {
    24             return Page();
    25         }
    26 
    27         [BindProperty]
    28         public Movie Movie { get; set; }
    29 
    30         // To protect from overposting attacks, please enable the specific properties you want to bind to, for
    31         // more details see https://aka.ms/RazorPagesCRUD.
    32         public async Task<IActionResult> OnPostAsync()
    33         {
    34             if (!ModelState.IsValid)
    35             {
    36                 return Page();
    37             }
    38 
    39             _context.Movie.Add(Movie);
    40             await _context.SaveChangesAsync();
    41 
    42             return RedirectToPage("./Index");
    43         }
    44     }
    45 }

       第22行:OnGet方法初始化页面所需的任何状态。Create页没有任何要初始化的状态,因此返回Page(),Page()方法创建用于呈现Create.cshtml页的PageResult对象。后面,我们会继续学习OnGet初始化状态的示例。

         第27、28行:使用[BindProperty]特性,来给Movie属性选择加入模型绑定。当Create页面发布表单值(form 标记)时,ASP.NET Core运行时将发布(post回传)的值绑定到Movie模型。

         第32行:当页面发布(post)表单(form)数据时,将运行OnGetAsync方法。

         第34-37行:如果不存在任何模型错误,将重新显示表单,以及post回的任何表单数据。在post回form前,在可以在客户端捕获到大部分的模型错误。模型错误的一个实例是:post回的日期字段值无法转换为日期。

         第39-42行:如果不存在模型错误,将保存数据。最后浏览器会重定向到Index页面。

      打开、更新Pages/Movies/Create.cshtml 的Razor页面:

      

     1 @page
     2 @model RazorPagesMovie.CreateModel
     3 
     4 @{
     5     ViewData["Title"] = "添加";
     6 }
     7 
     8 <h1>新增</h1>
     9 
    10 <h4>电影</h4>
    11 <hr />
    12 <div class="row">
    13     <div class="col-md-4">
    14         <form method="post">
    15             <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    16             <div class="form-group">
    17                 <label asp-for="Movie.Title" class="control-label">标题</label>
    18                 <input asp-for="Movie.Title" class="form-control" />
    19                 <span asp-validation-for="Movie.Title" class="text-danger"></span>
    20             </div>
    21             <div class="form-group">
    22                 <label asp-for="Movie.ReleaseDate" class="control-label">发布时间</label>
    23                 <input asp-for="Movie.ReleaseDate" class="form-control" />
    24                 <span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
    25             </div>
    26             <div class="form-group">
    27                 <label asp-for="Movie.Genre" class="control-label">题材</label>
    28                 <input asp-for="Movie.Genre" class="form-control" />
    29                 <span asp-validation-for="Movie.Genre" class="text-danger"></span>
    30             </div>
    31             <div class="form-group">
    32                 <label asp-for="Movie.Price" class="control-label">价格</label>
    33                 <input asp-for="Movie.Price" class="form-control" />
    34                 <span asp-validation-for="Movie.Price" class="text-danger"></span>
    35             </div>
    36             <div class="form-group">
    37                 <input type="submit" value="添加" class="btn btn-primary" />
    38             </div>
    39         </form>
    40     </div>
    41 </div>
    42 
    43 <div>
    44     <a asp-page="Index">返回到电影列表</a>
    45 </div>
    46 
    47 @section Scripts {
    48     @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    49 }

        第14行:表示这个元素是一个表单标记帮助程序(form tag helper)。表单标记帮助程序会自动包含防伪令牌(antiforgery token)。

        第15-34行:基架引擎在模型中为每个字段(除ID外)创建Razor标记。

          其中<div asp-validation-summary>和<span asp-validation-for>一起,用于显示验证错误。详细的验证信息以后再学习。

          <label asp-for="" class="">是标签标记帮助程序(label tag helper)。生成一个标签描述和Title属性的for特性。(这里我们手动更改为“标题”)。

          <input asp_for="" class="">使用DataAnnotations属性并在客户端生成jQuery验证所需的HTML属性。

     6、验证

      按下ctrl+F5,运行应用程序。测试我们更改的效果。

  • 相关阅读:
    C++虚函数表解析(转)
    学习网址
    css 段落文字换行问题
    移动端fixed兼容问题
    半数集1
    汇编寄存器
    设计模式概述
    Vector用法介绍
    汇编PC硬件基本特征
    android 反编译总结
  • 原文地址:https://www.cnblogs.com/hiwuchong/p/12081664.html
Copyright © 2020-2023  润新知