原文

什么是Razor Pages?

Razor pages是ASP.NET Core 2.0的新特性,它被设计用来更快的开发页面,比传统的MVC模式更便捷。

创建项目

为了使用Razor Pages,你须在安装Core 2.0。

在VS中,你可以通过选择File -> New Project,然后选择ASP.NET Core Web Application来创建一个新的Core Razor Pages项目:

现在,选择Web Application点击OK创建项目:

VS创建的Razor Page项目和其他的Core web项目的结构非常类似,不同的是多了一个Pages文件夹:

初始化项目的一些代码

public class Employee
{
[DisplayName("First Name:")]
[Required(ErrorMessage = "Please enter the employee's first name")]
public string FirstName { get; set; } [DisplayName("Last Name:")]
[Required(ErrorMessage = "Please enter the employee's last name")]
public string LastName { get; set; } [DisplayName("Date of Birth:")]
[DataType(DataType.Date)]
public DateTime DateOfBirth { get; set; } [DisplayName("ID:")]
[Required(ErrorMessage = "Please enter the employee's ID")]
public int ID { get; set; }
} public interface IEmployeeRepository
{
Employee GetByID(int id);
List<Employee> GetAll();
} public class EmployeeRepository : IEmployeeRepository
{
public List<Employee> GetAll()
{
List<Employee> employees = new List<Employee>();
employees.Add(GetByID(1));
employees.Add(GetByID(2));
employees.Add(GetByID(3));
return employees;
} public Employee GetByID(int id)
{
if(id == 1)
{
return new Employee()
{
FirstName = "Spencer",
LastName = "Strasmore",
DateOfBirth = new DateTime(1978, 11, 16),
ID = 1
};
}
if(id == 2)
{
return new Employee()
{
FirstName = "Ricky",
LastName = "Jerret",
DateOfBirth = new DateTime(1989, 3, 30),
ID = 2
};
}
if(id == 3)
{
return new Employee()
{
FirstName = "Vernon",
LastName = "Littlefield",
DateOfBirth = new DateTime(1992, 7, 3),
ID = 3
};
} return null;
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IEmployeeRepository, EmployeeRepository>();
...
}

新建首页

现在我们准备添加一个Razor Page用来展现employee列表。首先在Pages文件夹下面创建一个Employees文件夹:

右键Employees文件夹选择Add -> New Item弹出如下窗口:

选择Razor Page,命名为Index,点击OK。VS将创建一个index.cshtml文件和一个index.cshtml.cs文件:

现在,我们来看看index.cshtml文件默认的内容:

@page
@model IndexModel
@{
}

@page指令表示这个是一个Razor Page,@model表示这个页面的模型是一个IndexModel的实例。

但是IndexModel在哪呢?它在Index.cshmtl.cs文件里面:

public class IndexModel : PageModel
{
public void OnGet()
{
}
}

注意OnGet()方法。这个是Razor Page Get页面的一个标准的方法。

怎么在这个页面显示所有的employee呢?

展示Employee

首先,修改IndexModel,添加一个Employee集合的属性,修改OnGet()方法,以此来从数据源中加载所有的Employee。

public class IndexModel : PageModel
{
private IEmployeeRepository _employeeRepo;
public List<Employee> Employees { get; set; } public IndexModel(IEmployeeRepository userRepo)
{
_employeeRepo = userRepo;
}
public void OnGet()
{
Employees = _employeeRepo.GetAll();
}
}

修改Index.cshtml文件来展示employee:

@page
@using ASPNETCoreRazorPagesDemo.Pages.Employees @model IndexModel <h2>Employees</h2> <a asp-page="Add">Add an Employee</a> <h3>@Model.Message</h3> <table>
<thead>
<tr>
<th>
Name
</th>
<th>
Date of Birth
</th>
<th>
Employee ID
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach(var employee in Model.Employees)
{
<tr>
<td>
@(employee.FirstName + " " + employee.LastName)
</td>
<td>
@employee.DateOfBirth.ToShortDateString()
</td>
<td>
@employee.ID
</td>
<td>
<a asp-page="Edit" asp-route-id="@employee.ID">Edit</a>
</td>
</tr>
}
</tbody>
</table>

创建一个新增Employee的页面

在Employees文件夹中创建一个名为Add的Razor Page文件。

修改这个cshtml文件,添加一个Add表单:

<h2>Add an Employee</h2>
<a asp-page="Index">Back to Employees</a> <form method="post">
<div>
<div>
<label asp-for="Employee.FirstName"></label>
<input type="text" asp-for="Employee.FirstName" />
<span asp-validation-for="Employee.FirstName"></span>
</div>
<div>
<label asp-for="Employee.LastName"></label>
<input type="text" asp-for="Employee.LastName" />
<span asp-validation-for="Employee.LastName"></span>
</div>
<div>
<label asp-for="Employee.DateOfBirth"></label>
<input type="text" asp-for="Employee.DateOfBirth" />
<span asp-validation-for="Employee.DateOfBirth"></span>
</div>
<div>
<label asp-for="Employee.ID"></label>
<input type="text" asp-for="Employee.ID" />
<span asp-validation-for="Employee.ID"></span>
</div>
</div>
<div>
<input type="submit" value="Add as Manager" asp-page-handler="JoinManager" />
<input type="submit" value="Add as Employee" asp-page-handler="JoinEmployee"/>
</div>
</form>

注意我们有两个不同的提交按钮。每个按钮都有一个asp-page-handler属性,并都有一个唯一的值。

在这个演示中我们不需要code-behind类,因此我们删除了Add.cshtml.cs文件,直接在Add.cshtml文件中引入了@function指令。我们将使用OnPostJoinManageAsync()OnPostJoinEmployeeAsync()方法。

为了在Razor Page页面包含C#模型,得先引入@function指令:

@functions
{
[TempData]
public string Message { get; set; } [BindProperty]
public Employee Employee { get; set; } public async Task<IActionResult> OnPostJoinManagerAsync()
{
if (!ModelState.IsValid)
{
return Page();
} Message = Employee.FirstName + " " + Employee.LastName + " (ID " + Employee.ID.ToString() + ") would have been added as a Manager."; return RedirectToPage("Index");
} public async Task<IActionResult> OnPostJoinEmployeeAsync()
{
if (!ModelState.IsValid)
{
return Page();
} Message = Employee.FirstName + " " + Employee.LastName + " (ID " + Employee.ID.ToString() + ") would have been added as an Employee."; return RedirectToPage("Index");
}
}

会自动检查ModelState来验证输入是否合法。这两个OnPostXXXAsync()方法返回的是Page()RedirectToPage("index"),这两个都是在2.0中才有的。

最后请注意asp-page-hanlderOnPostJoinManagerAsync() OnPostJoinEmployeeAsync()方法的对应关系。

创建编辑页面

如上一样创建一个名为Edit的Razor Page,和Add页面不同的是,这次我们保留了Edit.cshtml.cs文件。

在这个文件中,我们需要修改模型,从数据源中加载Emploee:

public class EditModel : PageModel
{
private IEmployeeRepository _employeeRepo; public EditModel(IEmployeeRepository employeeRepo)
{
_employeeRepo = employeeRepo;
} [TempData]
public string Message { get; set; } [BindProperty]
public Employee Employee { get; set; } public async Task<IActionResult> OnGetAsync(int id)
{
Employee = _employeeRepo.GetByID(id); if(Employee == null)
{
return RedirectToPage("Index");
} return Page();
} public async Task<IActionResult> OnPostAsync()
{
if(!ModelState.IsValid)
{
return Page();
} Message = Employee.FirstName + " " + Employee.LastName + ", ID " + Employee.ID.ToString() + " would have been saved."; return RedirectToPage("Index");
}
}

.cshtml文件的内容如下:

@page "{id:int}"
@model ASPNETCoreRazorPagesDemo.Pages.Employees.EditModel <h2>Add an Employee</h2>
<a asp-page="Index">Back to Employees</a> <form method="post">
<div>
<div>
<label asp-for="Employee.FirstName"></label>
<input type="text" asp-for="Employee.FirstName" />
<span asp-validation-for="Employee.FirstName"></span>
</div>
<div>
<label asp-for="Employee.LastName"></label>
<input type="text" asp-for="Employee.LastName" />
<span asp-validation-for="Employee.LastName"></span>
</div>
<div>
<label asp-for="Employee.DateOfBirth"></label>
<input type="text" asp-for="Employee.DateOfBirth" />
<span asp-validation-for="Employee.DateOfBirth"></span>
</div>
<div>
<label asp-for="Employee.ID"></label>
<input type="text" asp-for="Employee.ID" />
<span asp-validation-for="Employee.ID"></span>
</div>
</div>
<div>
<input type="submit" value="Submit" />
</div>
</form>

路由

首先,如果你想要在路由上包含一些数据,你需要修改.cshtml文件的@page指令。在我们的Edit页面是这样的:

@page "{id:int}"

@page后面的字符串是路由的一部分。因为Edit页是Employees/Edit,因此完整的路由应该是/Employees/Edit/2。

接下来看看RedirectToPage()是怎么工作的,先看看Add页面:

return RedirectToPage("Index");

如果在文件夹中存在Index文件,那么用户会被重定向到这个页面,否则会抛出一个异常。如果一个路由映射到了两个不同的页面, Core会抛出AmbiguousActionException

Razor Page的特性

  1. Anti-forgery会自动包含在每个Razor Page页面。
  2. 不在需要ViewModels了,因为我们有了PageModel

Razor Page的内聚性比较好,因为所有和一个页面相关的数据都在和这个页面相关的一个独立的文件里面。 (不在需要在搞一个Controller, ViewModel了)。

[译]ASP.NET Core揭秘 - Razor Pages的更多相关文章

  1. asp.net core 的 razor pages 如何使用ajax调用后台方法

    Razor 是一种允许您向网页中嵌入基于服务器的代码(Visual Basic 和 C#)的标记语法. 当网页被写入浏览器时,基于服务器的代码能够创建动态内容. 在网页加载时,服务器在向浏览器返回页面 ...

  2. ASP.NET Core使用Razor页面

    ASP.NET Core使用Razor页面 Razor是ASP.NET的页面引擎,在ASP.NET MVC 3以后被广泛使用,我在之前的博客中有所介绍,需要更多了解的朋友请移步[Razor语法] 在A ...

  3. [译]ASP.NET Core 2.0 系列文章目录

    基础篇 [译]ASP.NET Core 2.0 中间件 [译]ASP.NET Core 2.0 带初始参数的中间件 [译]ASP.NET Core 2.0 依赖注入 [译]ASP.NET Core 2 ...

  4. 独立使用Asp.net Core 的razor模板 (一):Razor引擎的一些细节

    由于最近需要写一些界面稍微好看点的Winform程序,如果用原生控件,,想要达到好看的程度,需要花费比较大的功夫,因为之前使用过CefSharp,因此发觉如果是使用CEF+Html的方式,界面可以相对 ...

  5. C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志

    C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...

  6. [译]ASP.NET Core 2.0 视图引擎

    问题 如何在ASP.NET Core 2.0中使用Razor引擎来创建视图? 答案 新建一个空项目,修改Startup.cs,添加MVC服务和请求中间件: public void ConfigureS ...

  7. [译]ASP.NET Core 2.0 视图组件

    问题 如何在ASP.NET Core 2.0中使用视图组件? 答案 新建一个空项目,修改Startup类并添加MVC服务和中间件: public void ConfigureServices(ISer ...

  8. [译]ASP.NET Core 2.0 区域

    问题 如何将一个规模庞大的ASP.NET Core 2.0应用程序进行逻辑分组? 答案 新建一个ASP.NET Core 2.0空项目,修改Startup类,增加Mvc服务和中间件: public v ...

  9. [译]ASP.NET Core依赖注入深入讨论

    原文链接:ASP.NET Core Dependency Injection Deep Dive - Joonas W's blog 这篇文章我们来深入探讨ASP.NET Core.MVC Core中 ...

随机推荐

  1. 关于executemany()方法在不同OS和DB API下的不同表现的测试

    昨天在参照着网上写一段关于MySQL连接池的配合gevent多线程调用的代码时遇到了一个问题,自己写的代码根本不能多线程执行,比单会话插入数据慢太多,直到今天早上才发现问题所在,把DB API从MyS ...

  2. PYQT5登录界面跳转主界面方法

    该问题,有很多种方法,但是很多方法要么这个有问题,要么那个有问题,最后终于找到一种没问题的方法.记录一下: 参考地址:https://www.jianshu.com/p/d18ff36a78d6?fr ...

  3. 《神经网络算法与实现-基于Java语言》的读书笔记

    文章提纲 全书总评 读书笔记 C1.初识神经网络 C2.神经网络是如何学习的 C3.有监督学习(运用感知机) C4.无监督学习(自组织映射) Rreferences(参考文献) 全书总评 书本印刷质量 ...

  4. vector入门

    vector怎么用? vector是什么? 你可以把它理解为一个数阵: 调用#include<vector> 定义:vector<int>v[N];//开一个名字叫做v的数字串 ...

  5. Linux根据端口号查看进程PID

    1.命令lsof,以查找占用端口80为例,用法如下: [root@localhost nginx]# lsof -i:80 以上为没有进程占用80端口, [root@localhost sbin]# ...

  6. Windows API方式直接调用C#的DLL,支持多音字转拼音、Gzip解压缩、公式计算(VBA、C++、VB、Delphi甚至java都可以)

    原始链接 https://www.cnblogs.com/Charltsing/p/DllExport.html 这两年,我在VBA应用方面一直有几大痛点:1.多音字转拼音:2.64位下的GZIP解压 ...

  7. 基于 docker 的yapi(快速部署)

    1.使用官方的mongodb镜像 docker run --network yapi_net --ip 172.30.0.10  -d --name yapi_mongodb --restart al ...

  8. table 里输入rules 验证

    HTML <el-form ref='from' :model="fromData"> <el-table ref="tableman" bo ...

  9. sqlserver登录名权限和用户名权限语句设置

    在sqlserver的安全体系中分为登录名和用户名,登录名是用于登录整个数据库系统用的,用户名是针对各个具体的数据来创建的用户,所以针对权限设置要有这个两个用户进行分别设置,下面写下用语句设置这两个用 ...

  10. python并发编程之协程知识点

    由线程遗留下的问题:GIL导致多个线程不能真正的并行,CPython中多个线程不能并行 单线程实现并发:切换+保存状态 第一种方法:使用yield,yield可以保存状态.yield的状态保存与操作系 ...