欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-06-20 08:44:07
本节主要介绍在上一节中通过搭建基架而创建的Razor页面,并做一些UI改变。 一、创建、删除、详细信息和编辑页面 1、双击Pages/Movies/Index.cshtml.cs文件,这是一个Razor页面模型: ① 第13行:表示该Razor页面派生自PageModel。约定:PageModel派 ......

 

本节主要介绍在上一节中通过搭建基架而创建的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’一起。最终形成页面上我们看到的标题:

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

 

 

   ④ 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,运行应用程序。测试我们更改的效果。