如何在ASP.NET Core 2.0中使用Razor页面
如何在ASP.NET Core 2.0中使用Razor页面
问题
如何在ASP.NET Core 2.0中使用Razor页面
解
创建一个空的项目并修改Startup.cs文件以为MVC添加服务和中间件。
publicvoid ConfigureServices(
IServiceCollection services)
{
services.AddSingleton<IMovieService, MovieService>();
services.AddMvc();
}
publicvoid Configure(
IApplicationBuilder app,
IHostingEnvironment env)
{
app.UseMvc();
}
添加一个服务和域模型(IMovieService的实现只是示例源代码中的内存列表),
publicclass Movie
{
publicint Id { get; set; }
public string Title { get; set; }
publicint ReleaseYear { get; set; }
public string Summary { get; set; }
}
publicinterface IMovieService
{
List<Movie> GetMovies();
Movie GetMovie(int id);
void AddMovie(Movie item);
void UpdateMovie(Movie item);
void DeleteMovie(int id);
bool MovieExists(int id);
}
添加输入和输出模型(通过属性绑定接收和发送数据)。
publicclass MovieInputModel
{
publicint Id { get; set; }
[Required]
public string Title { get; set; }
publicint ReleaseYear { get; set; }
public string Summary { get; set; }
}
publicclass MovieOutputModel
{
publicint Id { get; set; }
public string Title { get; set; }
publicint ReleaseYear { get; set; }
public string Summary { get; set; }
public DateTime LastReadAt { get; set; }
}
添加一个名为Pages的文件夹,并为其添加Index,_Layout,_ViewImports和_ViewStart页面。这些页面与MVC没有区别。另外,为您的CRUD页面添加一个文件夹Movies。
添加4个新的RazorPage项目到电影文件夹 - 称为索引,创建,编辑和删除。这些将添加.cshtml和.cshtml.cs文件。
这些页面中的每一个都将通过构造器注入来注入我们的 IMovieService ,例如,
private readonly IMovieService service;
public IndexModel(IMovieService service)
{
this.service = service;
}
修改Index.cshtml。
@page
@model IndexModel
@{
}
<strong>Movie Listing</strong>
<div>
<a asp-page="/Index">Home</a> |
<a asp-page="./Create">Add New</a>
</div>
<table>
<thead>
<tr>
<th>Title</th>
<th>Year</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movies)
{
<tr>
<td>@item.Title</td>
<td>@item.ReleaseYear</td>
<td><a asp-page="./Edit" asp-route-id="@item.Id">Edit</a></td>
<td><a asp-page="./Delete" asp-route-id="@item.Id">Delete</a></td>
</tr>
}
</tbody>
</table>
修改Index.cshtml.cs。
public List<MovieOutputModel> Movies { get; set; }
publicvoid OnGet()
{
this.Movies = this.service.GetMovies()
.Select(item => new MovieOutputModel
{
Id = item.Id,
Title = item.Title,
ReleaseYear = item.ReleaseYear,
Summary = item.Summary,
LastReadAt = DateTime.Now
})
.ToList();
}
修改Create.cshtml。
@page
@model CreateModel
@{
}
<strong>New Movie</strong>
<form method="post">
<div asp-validation-summary="All"></div>
<label asp-for="Movie.Id"></label>
<input asp-for="Movie.Id" /><br />
<label asp-for="Movie.Title"></label>
<input asp-for="Movie.Title" />
<span asp-validation-for="Movie.Title"></span><br />
<label asp-for="Movie.ReleaseYear"></label>
<input asp-for="Movie.ReleaseYear" /><br />
<label asp-for="Movie.Summary"></label>
<textarea asp-for="Movie.Summary"></textarea><br />
<button type="submit">Save</button>
<a asp-page="./Index">Cancel</a>
</form>
修改Create.cshtml.cs。
[BindProperty]
public MovieInputModel Movie { get; set; }
publicvoid OnGet()
{
this.Movie = new MovieInputModel();
}
public IActionResult OnPost()
{
if (!ModelState.IsValid)
return Page();
var model = new Movie
{
Id = this.Movie.Id,
Title = this.Movie.Title,
ReleaseYear = this.Movie.ReleaseYear,
Summary = this.Movie.Summary
};
service.AddMovie(model);
return RedirectToPage("./Index");
}
修改Edit.cshtml。
@page "{id:int}"
@model EditModel
@{
}
<strong>Edit Movie - @Model.Movie.Title</strong>
<form method="post">
<div asp-validation-summary="All"></div>
<input type="hidden" asp-for="Movie.Id" />
<label asp-for="Movie.Title"></label>
<input asp-for="Movie.Title" />
<span asp-validation-for="Movie.Title"></span><br />
<label asp-for="Movie.ReleaseYear"></label>
<input asp-for="Movie.ReleaseYear" /><br />
<label asp-for="Movie.Summary"></label>
<textarea asp-for="Movie.Summary"></textarea><br />
<button type="submit">Save</button>
<a asp-page="./Index">Cancel</a>
</form>
修改Edit.cshtml.cs。
[BindProperty]
public MovieInputModel Movie { get; set; }
public IActionResult OnGet(int id)
{
var model = this.service.GetMovie(id);
if (model == null)
return RedirectToPage("./Index");
this.Movie = new MovieInputModel
{
Id = model.Id,
Title = model.Title,
ReleaseYear = model.ReleaseYear,
Summary = model.Summary
};
return Page();
}
public IActionResult OnPost()
{
if (!ModelState.IsValid)
return Page();
var model = new Movie
{
Id = this.Movie.Id,
Title = this.Movie.Title,
ReleaseYear = this.Movie.ReleaseYear,
Summary = this.Movie.Summary
};
service.UpdateMovie(model);
return RedirectToPage("./Index");
}
修改Delete.cshtml。
@page "{id:int}"
@model DeleteModel
@{
}
<strong>Delete Movie</strong>
<p>Are you sure you want to delete <strong>@Model.Title</strong>?</p>
<form method="post">
<input type="hidden" asp-for="Id" />
<button type="submit">Yes</button>
<a asp-page="./Index">No</a>
</form>
修改Delete.cshtml.cs。
[BindProperty]
publicint Id { get; set; }
public string Title { get; set; }
public IActionResult OnGet(int id)
{
var model = this.service.GetMovie(id);
if (model == null)
return RedirectToPage("./Index");
this.Id = model.Id;
this.Title = model.Title;
return Page();
}
public IActionResult OnPost()
{
if (!service.MovieExists(this.Id))
return RedirectToPage("./Index");
service.DeleteMovie(this.Id);
return RedirectToPage("./Index");
}
运行并浏览到/电影。
点击时,首先编辑(注意网址是/ Movies / Edit / 1),
点击删除(注意URL将是/电影/删除/ 3),
注意
你可以下载源代码来玩它。
讨论
在ASP.NET Core 2.0中引入了Razor页面,可以更快地构建简单的Web应用程序,并且是使用各种ASP.NET Core概念(如Razor,Layout Pages和Tag Helper等)的好方法。
Razor Pages使用 ASP.NET Core MVC ,但是编程模型不一样。与MVC不同,控制器,模型和视图是体系结构的不同组成部分,在Razor Pages中,这些概念被集中到一个页面模型的页面中。
页面模型
我喜欢将Page Model视为Controller和Models的组合。他们就像控制器,因为他们收到的HTTP请求,像一个模型,因为他们拥有视图的数据/属性。
对于.cshtml文件充当Page Model,它必须包含@page指令的第一行。.cshtml.cs(代码隐藏)类继承自PageModel抽象类。按照惯例,代码隐藏类有 模型 附加到页面的名称,例如索引页的代码隐藏是IndexModel。
路由
路由到页面取决于它们在您的项目目录结构中位于Pages文件夹下的位置(默认情况下)。如果URL中没有指定页面,则使用默认的索引。
在我们的示例中,我们导航到URL / Movies以查看位于我们的解决方案中的/ Pages / Movies / Index的页面。类似地,URL / Movies / Edit映射到/ Pages / Movies / Edit页面。
ASP.NET Core 2.0引入了用于生成URL的新构造,
Page()方法
asp页面标签助手
PageModel基类的RedirectToPage()方法
请注意,以/开头的URL是绝对路径并指向Pages文件夹。我们也可以使用与./或../相关的URL,或者简单的省略/。为了更好地理解,这里是从Page / Movies / Delete导航到各种URL时发生的情况,
我们可以将路由约束指定为@page指令的一部分,以指示运行时期望路由参数,或者丢失404(未找到)。在我们的编辑页面中,我们使用约束 -
@page “{id:int}”
如果您希望使用不同于Pages的名称作为根文件夹,则可以通过配置页面选项来实现。
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.RootDirectory = "/MyPages";
});
处理程序
如前所述,页面接收HTTP请求(即充当MVC世界中的Action),并由 处理程序方法处理。 这些处理程序返回IActionResult并使用On [verb]的约定命名。最常用的是OnGet()和OnPost()。对于异步,您可以将Async附加到名称,但是这是可选的。
PageModel基类具有RedirectToPage()方法(返回RedirectToPageResult)导航到其他页面和Page()方法(返回PageResult)返回当前页面。请注意,如果处理程序方法的返回类型为void,则运行时将返回PageResult。
为了让HTTP动词拥有多个处理器方法,我们可以使用 asp-page-handler属性来使用 命名处理器方法。这里指定的名字应该在页面类中使用约定On [动词] [处理程序]。让我们添加一个链接到我们的电影列表删除电影,
<td>
<a asp-page="./Index"
asp-page-handler="delete"
asp-route-id="@item.Id">Delete</a>
</td>
在页面模型类中添加一个方法来处理这个请求(注意它的名字和参数),
public IActionResult OnGetDelete(int id)
{
if (!service.MovieExists(id))
return RedirectToPage("./Index");
service.DeleteMovie(id);
return RedirectToPage("./Index");
}
将鼠标移到删除链接上,您会注意到像/ Movies?id = 1&handler = delete这样的URL。如果您希望用URL段替换查询参数,则将以下路由约束添加到@page指令,生成的URL将为/ Movies / delete / 1,
@page "{handler?}/{id:int?}"
捆绑
页面上的@model指令指向页面模型类,因为如前所述,该类充当Razor页面的模型。这适用于读取属性,但为了在发布数据时填充它们(即,当使用除GET之外的动词时),我们需要使用属性[BindProperty]来标记要使用模型绑定的属性。
如何在ASP.NET Core 2.0中使用Razor页面的更多相关文章
- 避免在ASP.NET Core 3.0中为启动类注入服务
本篇是如何升级到ASP.NET Core 3.0系列文章的第二篇. Part 1 - 将.NET Standard 2.0类库转换为.NET Core 3.0类库 Part 2 - IHostingE ...
- 如何在ASP.NET Core自定义中间件中读取Request.Body和Response.Body的内容?
原文:如何在ASP.NET Core自定义中间件中读取Request.Body和Response.Body的内容? 文章名称: 如何在ASP.NET Core自定义中间件读取Request.Body和 ...
- 如何在ASP.NET Core Web API中使用Mini Profiler
原文如何在ASP.NET Core Web API中使用Mini Profiler 由Anuraj发表于2019年11月25日星期一阅读时间:1分钟 ASPNETCoreMiniProfiler 这篇 ...
- ASP.NET Core 1.0 中的依赖项管理
var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...
- 在ASP.NET Core 1.0中如何发送邮件
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:目前.NET Core 1.0中并没有提供SMTP相关的类库,那么要如何从ASP.NE ...
- ASP.NET Core 1.0 中使用 Swagger 生成文档
github:https://github.com/domaindrivendev/Ahoy 之前文章有介绍在ASP.NET WebAPI 中使用Swagger生成文档,ASP.NET Core 1. ...
- 用ASP.NET Core 1.0中实现邮件发送功能
准备将一些项目迁移到 asp.net core 先从封装类库入手,在遇到邮件发送类时发现在 asp.net core 1.0中并示提供SMTP相关类库,于是网上一搜发现了MailKit 好东西一定要试 ...
- 在ASP.NET Core 2.0中使用CookieAuthentication
在ASP.NET Core中关于Security有两个容易混淆的概念一个是Authentication(认证),一个是Authorization(授权).而前者是确定用户是谁的过程,后者是围绕着他们允 ...
- ASP.NET Core 3.0中使用动态控制器路由
原文:Dynamic controller routing in ASP.NET Core 3.0 作者:Filip W 译文:https://www.cnblogs.com/lwqlun/p/114 ...
随机推荐
- golang之math/rand随机数
简单的随机数生成,结合时间模块初始化种子 package main import ( "fmt" "math/rand" "time" ) ...
- python 类函数
81定义: class 类名(object):# __init__(self, 参数列表): # __init__叫构造函数,其作用:使用类实例对象时,自动调用_init_,起到对象进行初始化, ...
- msys2 + clion安装所需的mingw64编译环境
pacman -S mingw-w64-x86_64-toolchain 输出结果为: $ pacman -S mingw-w64-x86_64-toolchain:: 在组 mingw-w64-x8 ...
- 修改RocketMQ的NameServer端口
---问题--- 有同事提出各个问题:如何修改RocketMQ的NameServer端口号?(默认:9876) ---结论--- 调查并验证之后,结论及过程如下: 验证版本:rocketmq-all- ...
- ST-LINK驱动的安装
1.下载ST-LINK驱动ST-LINK_USB_V2_1_Driver 双击dpinst_amd64.exe来安装. 成功会显示: 2.进入MDK5里面去配置ST-LINK 通过魔术棒选项: a.D ...
- Ubuntu 16.04调节屏幕显示字体大小
对于高分辨屏幕来说,Ubuntu的字体可能会有点小,反之,低分率的屏幕字体有点大,设置方法如下: [System Settings]->[Displays]->[ Scale for me ...
- StretchBlt函数和BitBlt函数的用法
StretchBlt和BitBlt都用在双缓冲视图中,用来显示一幅图像 一.StretchBlt 函数从源矩形中复制一个位图到目标矩形,必要时按目标设备设置的模式进行图像的拉伸或压缩.也即是将内存中的 ...
- Concurrent Request:Inactive phase,No Manager status
Symptom 随便submit一个request,发现几乎所有的Concurrent Manager都为No Manager状态,Phase为Inactive. Solution 一个Concurr ...
- 让FIREDAC记录数据库的异常日志
默认FIREDAC不会记录数据库的异常. 比如典型的,提交的时候,非空字段没有给值. 某些人还以为FIREDAC不能捕获数据库的异常,其实FIREDAC是可以捕获并处理数据库的异常事件的. 方法异常简 ...
- SqlServer循环执行存储过程
begin --申明变量 ) declare @zycs int --赋值变量 --申明游标 declare order_cursor cursor for (select blh, zycs fro ...