十年河东,十年河西,莫欺少年穷
学无止境,精益求精
概述:此教程介绍了生成 Razor Pages Web 应用的基础知识。具体分为如下部分
- 创建 Razor 页面 Web 应用
- 向 Razor 页面应用添加模型
- 基架(生成)Razor 页面
- 使用数据库
- 更新 Razor 页面
- 添加搜索
- 添加新字段
- 添加验证
首先,我们启用VS新建一个项目:
本篇主要是学习使用NetCore的Razor视图,因此先从最基本的添加项目开始。添加项目完成后,我们发现系统自动生成了以下各项,如下图:
首先我们对项目各文件的执行顺序作个说明:
与早期版本的 ASP.NET 对比,最显著的变化之一就是配置应用程序的方式, Global.asax、FilterConfig.cs 和 RouteConfig.cs 统统消失了,取而代之的是 Program.cs 和 Startup.cs。Program.cs 作为 Web 应用程序的默认入口,不做任何修改的情况下,会调用同目录下 Startup.cs 中的 ConfigureServices 方法 和 Configure 方法,最后执行Request Handle Start(个人认为就是路由指向的文件) ,譬如:https://localhost:44392/Movies/Details?id=4 执行的是上图Pages文件夹中的Movies文件夹中的Details.cshtml文件,其路由机制和MVC类似。
其次,一起探讨下各个文件夹/文件的作用:
Pages文件夹
1、模板文件,
例如:__Layout.cshtml,一般都放在Pages/Shared文件夹中,_Layout.cshtml 文件可配置所有页面通用的 UI 元素 。此文件设置页面顶部的导航菜单和页面底部的版权声明。
2、自定义的Razor页面
注意:自定义的Razor页面比模板页面会多出一个CS文件,这一点和.Net MVC中的CsHtml页面不一样,这个CS文件我们可以理解为页面的ViewModel,用于初始化页面及页面业务逻辑的相关操作,譬如:增删改查。
wwwroot 文件夹
包含静态文件,如 HTML 文件、JavaScript 文件和 CSS 文件。有关详细信息,请参阅ASP.NET Core 中的静态文件。
appSettings.json
包含配置数据,如连接字符串。有关详细信息,请参阅ASP.NET Core 中的配置。
Program.cs
包含程序的入口点。有关详细信息,请参阅.NET 通用主机。
Startup.cs
包含配置应用行为的代码。有关详细信息,请参阅ASP.NET Core 中的应用启动。
文件的简单介绍到此为止,下面我们来添加项目相关准备
1、新建一个数据库,命名为:MovieDB
2、创建一张表,命名为:Movie
脚本如下:
create tableMovie ( ID int identity(1,1) primary key, Title nvarchar(200), ReleaseDate datetime, Genre varchar(200), Price decimal(18,2) )
数据库创建完毕,我们插入一条数据:
insert into [MovieDB].[dbo].[Movie] values('战狼2',getdate(),'影视媒体',18)
至此,数据准备完毕,下面我们创建数据库链接字符串,打开appsettings.json文件,编辑如下:
新增链接字符串:
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"RazorPagesMovieContext": "Data Source=DESKTOP-VD79APR\SQLEXPRESS;Initial Catalog=MovieDB;Integrated Security=True"
}
}
注意上述链接字符串中的 RazorPagesMovieContext ,这是一个数据访问上下文,用于数据库对象(数据表)构建及数据访问,我们可以通过VS创建,下面会逐步介绍,现在我们需要准备和数据表对应的实体类Movie,如下:
在项目中添加DataModel文件夹,并添加类:Movie.cs 【类的属性和数据表字段对应,并添加了相关数据验证】,如下:
usingSystem; usingSystem.Collections.Generic; usingSystem.ComponentModel.DataAnnotations; usingSystem.ComponentModel.DataAnnotations.Schema; usingSystem.Linq; usingSystem.Threading.Tasks; namespaceRazorPagesMovie2.DataModel { public classMovie { public int ID { get; set; } [StringLength(60, MinimumLength = 3)] [Required] public string Title { get; set; } /// <summary> ///发布日期,Display:展示类型 DataType:数据类型 日期类型 /// </summary> [Display(Name = "Release Date")] [DataType(DataType.Date)] public DateTime ReleaseDate { get; set; } /// <summary> ///价格 范围1~100 货币类型 数字类型 /// </summary> [Range(1, 100)] [DataType(DataType.Currency)] [Column(TypeName = "decimal(18, 2)")] public decimal Price { get; set; } /// <summary> ///正则表达式 最大长度30 必填信息 /// </summary> [RegularExpression(@"^[A-Z]+[a-zA-Z""'s-]*$")] [Required] [StringLength(30)] public string Genre { get; set; } } }
上述准备完毕后,我们利用VS强大的数据模型绑定来构建增删改查页面,如下:
在Pages文件夹中新建文件夹MoviePages,如下:
右键MoviePages文件夹,选择:添加->新搭建基架的项目(F)...,用于创建增删改查页面及生成RazorPagesMovieContext数据库上下文访问类,如下:
需要将默认的:RazorPagesMovie2.Models.RazorPagesMovie2Context 修改为:RazorPagesMovie2.Data.RazorPagesMovie2Context ,以便生产一个名为Data的文件夹,用于区分Models文件夹。
这是会生产一个Data的文件夹,有一个类,名称为:RazorPagesMovie2Context ,也就是上述提到的数据库访问上下文类,用于数据库访问及数据库对象构建。
如下:
代码如下:
usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Threading.Tasks; usingMicrosoft.EntityFrameworkCore; usingRazorPagesMovie2.DataModel; namespaceRazorPagesMovie2.Data { public classRazorPagesMovie2Context : DbContext { public RazorPagesMovie2Context (DbContextOptions<RazorPagesMovie2Context>options) : base(options) { } public DbSet<RazorPagesMovie2.DataModel.Movie> Movie { get; set; } } }
同时在StartUp.cs中也会指定数据库访问链接字符串,如下:
注意:StartUp.cs 中的上下文名称应和appsettings.json 中的名称一致,如果不一致,会导致找不到链接字符串。
此时,项目基本构建完成,运行如下:
由上图可以,我们根据VS基架模板来生成的增删改查页面对应的.CS文件中有生成相应的增删改查代码,如下:
前端:
@page @model RazorPagesMovie2.Pages.MoviePages.IndexModel @{ ViewData["Title"] = "Index"; } <h2>Index</h2> <p> <a asp-page="Create">Create New</a> </p> <table class="table"> <thead> <tr> <th>@Html.DisplayNameFor(model => model.Movie[0].Title) </th> <th>@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate) </th> <th>@Html.DisplayNameFor(model => model.Movie[0].Price) </th> <th>@Html.DisplayNameFor(model => model.Movie[0].Genre) </th> <th></th> </tr> </thead> <tbody>@foreach (var item in Model.Movie) { <tr> <td>@Html.DisplayFor(modelItem => item.Title) </td> <td>@Html.DisplayFor(modelItem => item.ReleaseDate) </td> <td>@Html.DisplayFor(modelItem => item.Price) </td> <td>@Html.DisplayFor(modelItem => item.Genre) </td> <td> <a asp-page="./Edit"asp-route-id="@item.ID">Edit</a>| <a asp-page="./Details"asp-route-id="@item.ID">Details</a>| <a asp-page="./Delete"asp-route-id="@item.ID">Delete</a> </td> </tr>} </tbody> </table>
查询代码:
public classIndexModel : PageModel { private readonlyRazorPagesMovie2.Data.RazorPagesMovie2Context _context; publicIndexModel(RazorPagesMovie2.Data.RazorPagesMovie2Context context) { _context =context; } public IList<Movie> Movie { get;set; } public asyncTask OnGetAsync() { Movie = await_context.Movie.ToListAsync(); } }
查询表中所有数据,当然,在EF NETCore中也支持Linq查询,如下:
public asyncTask OnGetAsync() { var movies = from m in_context.Movie selectm; if (!string.IsNullOrEmpty(SearchString)) { movies = movies.Where(s =>s.Title.Contains(SearchString)); } Movie = awaitmovies.ToListAsync(); }
增加页面代码如下:
usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Threading.Tasks; usingMicrosoft.AspNetCore.Mvc; usingMicrosoft.AspNetCore.Mvc.RazorPages; usingMicrosoft.AspNetCore.Mvc.Rendering; usingRazorPagesMovie2.Data; usingRazorPagesMovie2.DataModel; namespaceRazorPagesMovie2.Pages.MoviePages { public classCreateModel : PageModel { private readonlyRazorPagesMovie2.Data.RazorPagesMovie2Context _context; publicCreateModel(RazorPagesMovie2.Data.RazorPagesMovie2Context context) { _context =context; } publicIActionResult OnGet() { returnPage(); } [BindProperty] public Movie Movie { get; set; } public async Task<IActionResult>OnPostAsync() { if (!ModelState.IsValid) { returnPage(); } _context.Movie.Add(Movie); await_context.SaveChangesAsync(); return RedirectToPage("./Index"); } } }
看到:await _context.SaveChangesAsync();是不是很熟悉,.SaveChanges其实就是EF增加删除更新的最常用方法,呵呵。
前端:
@page @model RazorPagesMovie2.Pages.MoviePages.CreateModel @{ ViewData["Title"] = "Create"; } <h2>Create</h2> <h4>Movie</h4> <hr /> <div class="row"> <div class="col-md-4"> <form method="post"> <div asp-validation-summary="ModelOnly"class="text-danger"></div> <div class="form-group"> <label asp-for="Movie.Title"class="control-label"></label> <input asp-for="Movie.Title"class="form-control" /> <span asp-validation-for="Movie.Title"class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Movie.ReleaseDate"class="control-label"></label> <input asp-for="Movie.ReleaseDate"class="form-control" /> <span asp-validation-for="Movie.ReleaseDate"class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Movie.Price"class="control-label"></label> <input asp-for="Movie.Price"class="form-control" /> <span asp-validation-for="Movie.Price"class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Movie.Genre"class="control-label"></label> <input asp-for="Movie.Genre"class="form-control" /> <span asp-validation-for="Movie.Genre"class="text-danger"></span> </div> <div class="form-group"> <input type="submit"value="Create"class="btn btn-default" /> </div> </form> </div> </div> <div> <a asp-page="Index">Back to List</a> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} }
就不一一展示了,大家可参考自己的项目进行学习
参考来自:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/razor-pages/?view=aspnetcore-3.1
@天才卧龙的博客