这里介绍了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. selenium-05-问题2

    现在的项目组用开源的Selenium做测试,但不得不说,这个东东bug奇多,下面是我遇到的一些问题,有些提供了解决方法,有些则需要继续研究,希望对各位看官有所帮助. 一.不能从命令行运行Seleniu ...

  2. mybatis #{}和${}的区别是什么?

    #{}是预编译处理,${}是字符串替换.mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值,最后注入进去是带引号的:mybatis在 ...

  3. 23种设计模式之单例(Singleton Pattern)

    单例 在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例(eg:应对一些特殊情况,比如数据库连接池(内置了资源)  全局唯一号码生成器),才能确保它们的逻辑正确性.以及良好的效率 ...

  4. C# 反射Reflection——反射反射程序员的快乐

    一.什么是反射 反射Reflection:System.Reflection,是.Net Framework提供的一个帮助类库,可以读取并使用metadata. 反射是无处不在的,MVC-Asp.Ne ...

  5. rt.jar包添加源文件只需要关联到已安装对应jdk目录下source.zip源码文件即可

    项目中配置的JRE System Libriry下的rt.jar包,需要关联源文件时候,只需要点击“Attach Source...“按钮,选择"External File..." ...

  6. 异步Promise及Async/Await最完整入门攻略

    一.为什么有Async/Await? 我们都知道已经有了Promise的解决方案了,为什么还要ES7提出新的Async/Await标准呢? 答案其实也显而易见:Promise虽然跳出了异步嵌套的怪圈, ...

  7. 蓝松SDK - 卡点视频制作介绍

    ---恢复内容开始--- 说明:卡点视频:是指随音频的节拍来不断的切换照片做成的一种 动感视频效果.卡点是卡的音乐中节奏切换的时间点, 在这些时间点上动态切换一个图片, 并给图片做各种动画,从而形成或 ...

  8. selenium实现百度图片爬取

    因为是百度图片是瀑布流ajax异步上传的数据,所以这里用到抓包工具来抓取链接(fiddler) 好了直接上代码, from selenium import webdriver from seleniu ...

  9. CSS技巧 (2) · 多列等高布局

    前言  最近,面试的时候都碰到一些关于利用CSS实现多列等高布局或者一侧宽度固定,另一侧宽度自适应的问题,下面稍微总结一下: 先看一道题目 巧妙的多列等高布局 规定下面的布局,实现多列等高布局,要求两 ...

  10. 利用JVM在线调试工具排查线上问题

    在生产上我们经常会碰到一些不好排查的问题,例如线程安全问题,用最简单的threaddump或者heapdump不好查到问题原因.为了排查这些问题,有时我们会临时加一些日志,比如在一些关键的函数里打印出 ...