这里介绍了Razor基本用法

  1. 创建带PageModel的Razor 页面
  2. 使用数据库
  3. 展示数据
  4. 更新数据
  5. 筛选器

准备工作

  1. 初始化空的项目(终端输入:dotnet new web -n=Razor)
  2. Nuget添加Microsoft.EntityFrameworkCore.SqlServer 和 Microsoft.EntityFrameworkCore.Design 
  3. 添加必要服务

   ConfigureServices添加Razor支持

public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
}

  修改app.UseEndpoints为

app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});

添加数据库

 1. 添加模型
[Table("Book")]
public class Book
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; } [Display(Name = "书名")]
[Required(ErrorMessage = "书名不能为空")]
[StringLength(, ErrorMessage = "书名最大长度为50")]
public string Name { get; set; } [Display(Name = "单价")]
[Column(TypeName = "decimal(18, 2)")]
[Range(0.01, , ErrorMessage = "单价范围只能在(0.01 ~ 10000)"), DataType(DataType.Currency)]
public decimal UnitPrice { get; set; } [Display(Name = "出版日期")]
[DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}")]
public DateTime PublicationDate { get; set; } [Display(Name = "创建时间")]
[DataType(DataType.DateTime), DisplayFormat(DataFormatString = "{0:yyyy-MM-dd HH:mm:ss}")]
public DateTime CreateTime { get; set; } [Display(Name = "最后更新时间")]
[DataType(DataType.DateTime), DisplayFormat(DataFormatString = "{0:yyyy-MM-dd HH:mm:ss}")]
public DateTime? LastUpdateTime { get; set; }
}

2. 添加DbContext

public class RazorDbContext : DbContext
{
public RazorDbContext(DbContextOptions<RazorDbContext> options)
: base(options)
{ } public DbSet<Razor.Models.Book> Book { get; set; }
}

3. 安装dotnet-ef(全局安装),终端输入

dotnet tool install --global dotnet-ef
4. 添加迁移
dotnet ef migrations add InitialDb

5. 更新到数据库

dotnet ef database update InitialDb

6. 添加种子数据

public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
var options = serviceProvider.GetRequiredService<DbContextOptions<RazorDbContext>>();
using (var context = new RazorDbContext(options))
{
if (context.Book.Any())
{
return;
} context.Book.AddRange(
new Models.Book
{
Name = "算法之美",
UnitPrice = 26.99m,
PublicationDate = DateTime.Parse("2016-08-20"),
CreateTime = DateTime.Now
},
new Models.Book
{
Name = "大话设计模式",
UnitPrice = 28.03m,
PublicationDate = DateTime.Parse("2015-06-12"),
CreateTime = DateTime.Now
},
new Models.Book
{
Name = "幸福的陷阱",
UnitPrice = 30.59m,
PublicationDate = DateTime.Parse("2018-09-13"),
CreateTime = DateTime.Now
},
new Models.Book
{
Name = "墨菲定律",
UnitPrice = 32.12m,
PublicationDate = DateTime.Parse("2018-09-13"),
CreateTime = DateTime.Now
}
); context.SaveChanges();
}
}
}

经过上面的步骤就可以在程序中使用数据库

Razor页面

一、路由
@page指令
  1. 必须是页面上的第一个 Razor 指令
  2. 默认情况,Url根据文件夹层次结构生成,也可以在@page 后面指定路由
  3. 可以对参数约束,例如:{id:int}

二、读取数据(以上面模型为例)

  1. 创建Index页面

dotnet new page -o=Pages -na="Razor.Pages" -n="Index"

  2. PageModel 的OnGet读取数据

public class IndexModel : PageModel
{
private readonly Data.RazorDbContext _dbContext;
public IndexModel(Data.RazorDbContext dbContext)
{
_dbContext = dbContext;
} public List<Models.Book> Books { get; set; } public IActionResult OnGet()
{
if (_dbContext == null)
{
return NotFound();
} Books = _dbContext.Book
.AsNoTracking()
.ToList();
return Page();
}
}

  3. 页面展示数据

@page
@model IndexModel
@{
ViewData["Title"] = "图书管理";
}
<table class="table table-bordered text-center">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Books[].Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Books[].UnitPrice)
</th>
<th>
@Html.DisplayNameFor(model => model.Books[].PublicationDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Books[].CreateTime)
</th>
<th >
@Html.DisplayNameFor(model => model.Books[].LastUpdateTime)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Books)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.UnitPrice)
</td>
<td>
@Html.DisplayFor(modelItem => item.PublicationDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.CreateTime)
</td>
<td>
@Html.DisplayFor(modelItem => item.LastUpdateTime)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.Id">编辑</a> |
<a asp-page="./Delete" asp-route-id="@item.Id">删除</a>
</td>
</tr>
}
</tbody>
</table>

三、更新数据

  1. 创建Edit页面

dotnet new page -o=Pages -na="Razor.Pages" -n="Edit"

  2. PageModel拉去数据

public IActionResult OnGet(int? id)
{
if (id == null)
{
return NotFound();
} Book = _dbContext.Book
.AsNoTracking()
.FirstOrDefault(m => m.Id == id); if(Book == null)
{
return NotFound();
} return Page();
}

  3. 编辑Edit页面

@page "{id:int}"
@model Razor.Pages.EditModel
@{
ViewData["Title"] = "编辑书本";
}
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Book.Id" />
<div class="form-group">
<label asp-for="Book.Name" class="control-label"></label>
<input asp-for="Book.Name" class="form-control" />
<span asp-validation-for="Book.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Book.UnitPrice" class="control-label"></label>
<input asp-for="Book.UnitPrice" class="form-control" />
<span asp-validation-for="Book.UnitPrice" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Book.PublicationDate" class="control-label"></label>
<input asp-for="Book.PublicationDate" class="form-control" />
<span asp-validation-for="Book.PublicationDate" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="保存" class="btn btn-primary" />
</div>
</form>
</div>
</div>

  4. OnPost处理请求

public IActionResult OnPost()
{
if (!ModelState.IsValid)
{
return Page();
} var model = _dbContext.Book.FirstOrDefault(m => m.Id == Book.Id); if (model == null)
{
return NotFound();
} model.Name = Book.Name;
model.PublicationDate = Book.PublicationDate;
model.UnitPrice = Book.UnitPrice; _dbContext.SaveChanges(); return RedirectToPage("Index");
}

用asp-for生成的输入框,会加上客户端验证,查看原代码可以发现

<input class="form-control" type="text" data-val="true" data-val-length="书名最大长度为50" data-val-length-max="50" data-val-required="书名不能为空" id="Book_Name" maxlength="50" name="Book.Name" value="大话设计模式" />

它是根据模型定义的验证,生成属性,然后用jquery-validation验证,这样我们没有写一行前端代码就能达到客户端验证效果,微软真的把DRY做到极致。当然后端的验证也是不能漏的

筛选器

Razor 页面筛选器提供的以下方法可在全局或页面级应用:

同步方法:

  • OnPageHandlerSelected:在选择处理程序方法后但在模型绑定发生前调用。
  • OnPageHandlerExecuting:在执行处理器方法前,模型绑定完成后调用。
  • OnPageHandlerExecuted:在执行处理器方法后,生成操作结果前调用。

异步方法:

  • OnPageHandlerSelectionAsync:在选择处理程序方法后,但在模型绑定发生前,进行异步调用。
  • OnPageHandlerExecutionAsync:在调用处理程序方法前,但在模型绑定结束后,进行异步调用。
一、全局筛选器
  1. 创建GlobalPageFilter类,实现IPageFilter接口
public class GlobalPageFilter : IPageFilter
{
private readonly ILogger _logger; public GlobalPageFilter(ILogger logger)
{
_logger = logger;
} public void OnPageHandlerExecuted(PageHandlerExecutedContext context)
{
_logger.LogDebug("Global Filter OnPageHandlerSelected called.");
} public void OnPageHandlerExecuting(PageHandlerExecutingContext context)
{
_logger.LogDebug("Global Filter OnPageHandlerExecuting called.");
} public void OnPageHandlerSelected(PageHandlerSelectedContext context)
{
_logger.LogDebug("Global Filter OnPageHandlerSelected called.");
}
}

  2. 创建过滤器工厂类,实现IFilterFactory接口

public class GlobalPagerFilterWithFactory : IFilterFactory
{
public bool IsReusable => false; public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
var logger = serviceProvider.GetService<ILogger<Filters.GlobalPageFilter>>(); return new Filters.GlobalPageFilter(logger);
}
}

  3. ConfigureServices添加RazorPage选项

services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.Conventions.ConfigureFilter(new Factories.GlobalPagerFilterWithFactory());
});

二、特定PageModel筛选器

  在PageModel里面重载
public override void OnPageHandlerSelected(Microsoft.AspNetCore.Mvc.Filters.PageHandlerSelectedContext context)
{
_logger.LogDebug("OnPageHandlerSelected");
}
//在执行处理器方法前,模型绑定完成后调用
public override void OnPageHandlerExecuting(Microsoft.AspNetCore.Mvc.Filters.PageHandlerExecutingContext context)
{
_logger.LogDebug("OnPageHandlerExecuting");
}
//在执行处理器方法后,生成操作结果前调用
public override void OnPageHandlerExecuted(Microsoft.AspNetCore.Mvc.Filters.PageHandlerExecutedContext context)
{
_logger.LogDebug("OnPageHandlerExecuted");
}

示例代码:https://github.com/WilsonPan/AspNetCoreExamples/tree/master/Razor

【ASP.NET Core学习】Razor页面的更多相关文章

  1. ASP.NET Core使用Razor页面

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

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

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

  3. WebAPI调用笔记 ASP.NET CORE 学习之自定义异常处理 MySQL数据库查询优化建议 .NET操作XML文件之泛型集合的序列化与反序列化 Asp.Net Core 轻松学-多线程之Task快速上手 Asp.Net Core 轻松学-多线程之Task(补充)

    WebAPI调用笔记   前言 即时通信项目中初次调用OA接口遇到了一些问题,因为本人从业后几乎一直做CS端项目,一个简单的WebAPI调用居然浪费了不少时间,特此记录. 接口描述 首先说明一下,基于 ...

  4. Asp.Net Core学习笔记:入门篇

    Asp.Net Core 学习 基于.Net Core 2.2版本的学习笔记. 常识 像Django那样自动检查代码更新,自动重载服务器(太方便了) dotnet watch run 托管设置 设置项 ...

  5. ASP.NET Core学习系列

    .NET Core ASP.NET Core ASP.NET Core学习之一 入门简介 ASP.NET Core学习之二 菜鸟踩坑 ASP.NET Core学习之三 NLog日志 ASP.NET C ...

  6. ASP.NET Core学习指导

    ASP.NET Core 学习指导 "工欲善其事必先利其器".我们在做事情之前,总应该做好充分的准备,熟悉自己的工具.就像玩游戏有一些最低配置一样,学习一个新的框架,也需要有一些基 ...

  7. Asp.Net Core 学习教程2、使用ASP.NET Core中的RazorPages

    1.创建一个Asp.Net Core Web应用程序 1.1.打开VS2019 新建项目 1.2.选好项目位置后进入线面界面,选择Web应用程序 1.3.进去的页面结构如下 Pages 文件夹:包含 ...

  8. ASP.NET Core 学习笔记 第一篇 ASP.NET Core初探

    前言 因为工作原因博客断断续续更新,其实在很早以前就有想法做一套关于ASP.NET CORE整体学习度路线,整体来说国内的环境的.NET生态环境还是相对比较严峻的,但是干一行爱一行,还是希望更多人加入 ...

  9. ASP.NET Core学习零散记录

    赶着潮流听着歌,学着.net玩着Core 竹子学Core,目前主要看老A(http://www.cnblogs.com/artech/)和tom大叔的博客(http://www.cnblogs.com ...

随机推荐

  1. 对Servlet执行流程的初步认识

    这里我们以Post方式请求Serclet为例 1.找到 中的URL地址 Form表单的Post请求HelloServlet(Action="HelloServlet")发起时, A ...

  2. Spring 梳理-容器(container)

    虽然Spring的组件代码是轻量级的,但它的配置却是重量级的.一开始,Spring用XML配置,而且是很多XML配置.Spring 2.5引入了基于注解的组件扫描,这消除了大量针对应用程序自身组件的显 ...

  3. .Net Core中间件和过滤器实现错误日志记录

    1.中间件的概念 ASP.NET Core的处理流程是一个管道,中间件是组装到应用程序管道中用来处理请求和响应的组件. 每个中间件可以: 选择是否将请求传递给管道中的下一个组件. 可以在调用管道中的下 ...

  4. pyinstaller程序打包工具

    PyInstaller是一个能将Python程序转换成单个可执行文件的程序, 操作系统支持Windows, Linux, Mac OS X, Solaris和AIX.并且很多包都支持开箱即用,不依赖环 ...

  5. 利用百度云接口实现车牌识别·python

    一个小需求---实现车牌识别. 目前有两个想法 1. 调云在线的接口或者使用SDK做开发(配置环境和变异第三方库麻烦,当然使用python可以避免这些问题) 2. 自己实现车牌识别算法(复杂) 一开始 ...

  6. .Net Core 商城微服务项目系列(九):使用Jenkins构建自动发布

    1.首先通过Docker运行Consul,并保证各个服务都成功注册: 然后运行jenkins,对MI.Web项目进行发布构建,至于怎么配置之前已经写过了,和上一篇一模一样,这里贴下批处理命令: cd ...

  7. restapi(7)- 谈谈函数式编程的思维模式和习惯

    国庆前,参与了一个c# .net 项目,真正重新体验了一把搬砖感觉:在一个多月时间好像不加任何思考,不断敲键盘加代码.我想,这也许是行业内大部分中小型公司程序猿的真实写照:都是坐在电脑前的搬砖工人.不 ...

  8. SpringBootSecurity学习(16)前后端分离版之 OAuth2.0 加密配置

    示例代码的改进 前面使用spring cloud security和spring cloud oauth2写了一个第三方授权的例子,例子非常的简单,主要目的是用来熟悉OAuth2.0 申请授权的整个流 ...

  9. SpringBoot 连接kafka ssl 报 CertificateException: No subject alternative names present 异常解决

    当使用较新版本SpringBoot时,对应的 kafka-client 版本也比较新,如果使用了 2.x 以上的 kafka-client ,并且配置了 kafka ssl 连接方式时,可能会报如下异 ...

  10. Scala 异常处理

    Scala 异常处理: parseURL("www.baidu.com") 会返回一个 Success[URL] ,包含了解析后的网址, 反之 parseULR("www ...