Create a RazorPagesMovie project based on ASP.NET core 3.1 - Razor page interpretation and update of the built base frame

Keywords: Attribute Lambda JQuery

This section mainly introduces the Razor page created by building the base frame in the previous section, and makes some UI changes.

1, Create, delete, detail and edit pages

1. Double click the Pages/Movies/Index.cshtml.cs file, which is a Razor page model:

  

 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 }

 

 

(1) line 13: indicates that the Razor page is derived from PageModel. Convention: the class derived from PageModel is called < pagename > model.

(2) line 17: indicates that this is a constructor. Use dependency injection to add RazorPagesMovieContent to the page. All the pages that have been built base frame follow this pattern.

③ line 24: indicates that when a request is made for a page, the OnGetAsync method returns the Movie list to the Razor page. Call OnGetAsync or OnGet to initialize the state of the page. The OnGetAsync method displays the list of obtained movies. Any return statement is used when OnGet returns void or OnGetAsync returns task. Because the Movie object returned at this time is defined in the program (line 22)

2. Double click the Pages/Movies/Create.cshtml.cs file, which is also a Razor page model:

 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 }

 

④ lines 32 and 22: when the return type is iationresult or task < iationresult >, the return statement must be provided.

3. Double click the Pages/Movies/Index.cshtml file. This is a Razor page:

 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 can be converted from HTML to C or razor specific tags. When the @ symbol is followed by a razor reserved keyword, it is converted to a razor specific tag, otherwise it is converted to C ා.

① line 1: @ page instruction, which is an example of a Razor instruction. This instruction represents converting a file to an MVC operation. This means that it can handle requests. @Page must be the first Razor instruction on the page.

Line 17-26: @ HTML this is a series of HTML helper programs using Lambda expressions. The DisplayNameFor HTML helper checks the attributes such as Tile and ReleaseDate referenced by the Lambda expression to determine the display name. Checking Lambda expressions, not evaluations, means that when model, model.Movie, or model.Movie[0] is null or empty, there is no access violation.

(3) line 35-44: @ Html.DisplayFor is to evaluate Lambda expression and get the attribute value of the model.

④ line 2: the @ model command, which specifies the model type passed to the Razor page. The model type in this example is the IndexModel model derived from the PageModel class in paragraph 1.

⑤ lines 4-6: there is no Razor keyword after the @ symbol, indicating that this is an example of C ා. {} the curly braces are the C ා code blocks. The reference model of this page is IndexModel, which is derived from PageModel. The PageModel base class contains the ViewData dictionary property, which can be used to transfer data to a view. We can add objects to the ViewData dictionary in the mode of key value pairs. Here, the Title property is added to the ViewData dictionary. The "Title" attribute is used in the / pages / shared / layout.cshtml file. See note 3 in Section 4.

4. Double click the / pages / shared / [layout.cshtml file

 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>

This is a template for page layout (similar to master page). It allows the HTML container to have the following layout: specified in one location; applied to multiple pages in the site.

(2) line 34: @ RenderBody(), is a placeholder to display all page specific views.

③ line 6: use @ ViewData["Title"] to get the value of the object "Title" in the dictionary, together with the string '- RazorPagesMovie'. Finally form the Title we see on the page:

  

 

 

④ the way to annotate the Razor page is: @ * annotate the content * @ (different from the HTML comment <! -- comment -- >. Comments will not be sent to the client

 

5. Update layout

① change Title and link page

/ pages / shared / [layout.cshtml file:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
< title > @ viewdata ["title"] - movie < / 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" > My Movies</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>
















 

There are two changes:

< title > @ viewdata ["title"] - movie < / Title >

< a class = "navbar brand" ASP page = "/ movies / index" > My Movies</a>

The second change, the original code is: ASP area = "" ASP page = "/ Movies/Index" >, which represents a markup helper. After the change, it is an anchor marker helper. ASP page = "/ Movies/Index" marks the properties and values of the helper to create a connection to the Razor page of / Movies/Index. Where, the value of the ASP area attribute is empty, indicating that the area is not used in the connection.

Pages/Movies/Index.cshtml file:

@page
@model RazorPagesMovie.IndexModel

@{
ViewData["Title"] = "home page";
}

<h1>Home page</h1>

 

Set the Layout property in pages / ﹣ viewstart.cshtml:

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

 

This flag sets the layout file to Pages / shared / [layout.cshtml under the Pages folder for all Razor files.

Pages/Movies/Create.cshtml.cs file:

 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 }

 

Line 22: any state the OnGet method needs to initialize the page. The Create page does not have any state to initialize, so the Page() method is returned to Create a PageResult object to render the Create.cshtml page. Later, we will continue to learn the example of OnGet initialization state.

Lines 27 and 28: use the [BindProperty] property to add model binding to the Movie property selection. When the Create page publishes form values (form tags), the ASP.NET Core runtime binds the published (post returned) values to the Movie model.

Line 32: the OnGetAsync method runs when the page publishes form data.

Line 34-37: if there are no model errors, the form is redisplayed, along with any form data returned by post. Before post back to form, most model errors can be caught on the client side. An example of a model error is that the date field value returned by post cannot be converted to a date.

Lines 39-42: if there are no model errors, the data is saved. Finally, the browser redirects to the Index page.

Open and update the Razor page of Pages/Movies/Create.cshtml:

  

 1 @page
 2 @model RazorPagesMovie.CreateModel
 3 
 4 @{
 5     ViewData["Title"] = "Add to";
 6 }
 7 
 8 <h1>Newly added</h1>
 9 
10 <h4>Film</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">Title</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">Release time</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">theme</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">Price</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="Add to" class="btn btn-primary" />
38             </div>
39         </form>
40     </div>
41 </div>
42 
43 <div>
44     <a asp-page="Index">Return to movie list</a>
45 </div>
46 
47 @section Scripts {
48     @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
49 }

 

 

Line 14: indicates that this element is a form tag helper. The form tag helper automatically contains an anti forgery token.

Lines 15-34: the base frame engine creates a Razor tag in the model for each field (except ID).

Where < div ASP validation summary > and < span ASP validation for > are used to display validation errors. Detailed verification information will be learned later.

< label ASP for = "" class = "" > is a label tag helper. Generate a for attribute for the label description and Title attribute. (here we manually change to "Title").

< input asp_for = "" class = "" > use the DataAnnotations property and generate the HTML properties required for jQuery validation on the client side.

6. Verification

Press ctrl+F5 to run the application. Test the effect of our changes.

Posted by jolle99 on Sun, 26 Apr 2020 21:02:03 -0700