一. Razor介绍

  在使用ASP.NET Core Web开发时, ASP.NET Core MVC 提供了一个新特性Razor。 这样开发Web包括了MVC框架和Razor框架。对于Razor来说它是一个新特性,在官方介绍ASP.NET Core的优点中提到“Razor Pages可以使基于页面的编码方式更简单高效”。

  1.1 Razor结构介绍

    (1) Pages文件夹

存放所有Razor页面,包括Razor 页面和支持文件。 每个 Razor 页面都是一对文件:

一个 .cshtml 文件,其中包含使用 Razor 语法的 C# 代码的 HTML 标记。

一个 .cshtml.cs 文件,其中包含处理页面事件的 C# 代码。

支持文件的名称以下划线开头。 例如,_Layout.cshtml 文件可配置所有页面通用的 UI 元素。 此文件设置页面顶部的导航菜单和页面底部的版权声明(后面讲布局时再介绍)。

    (2) wwwroot 文件夹

包含静态文件,如 HTML 文件、JavaScript 文件和 CSS 文件(后面再讲)。

    (3) appSettings.json

包含配置数据,如连接字符串。参考asp.net core 系列第 10和11篇

    (4) Program.cs

包含程序的入口点,启动主机。参考asp.net core 系列第 16和17篇

    (5) startup.cs

包含配置应用行为的代码,例如,是否需要同意 cookie。参考asp.net core 系列第 2篇

    

  1.2  启动Razor关键代码

  1. public class Startup
  2. {
  3. public void ConfigureServices(IServiceCollection services)
  4. {
  5. // Includes support for Razor Pages and controllers.
  6. services.AddMvc();
  7. }
  8.  
  9. public void Configure(IApplicationBuilder app)
  10. {
  11. app.UseMvc();
  12. }
  13. }

  1.3  @page指令

    对于每一个Razor 页面,在.cshtml视图文件中,@page指令必须是页面上的第一个 Razor 指令。@page 使文件转换为一个 MVC 操作 ,这意味着它将直接处理请求, 而不通过控制器(Controllers)处理。@page 将影响其他 Razor 构造的行为。下面是一个直接处理请求的示例:

  1. //index.cshtml.cs
  2. public class IndexModel : PageModel
  3. {
  4. public string Message { get; private set; } = "PageModel in C#";
  5.  
  6. //加载时调用
  7. public void OnGet()
  8. {
  9. Message += $" Server time is { DateTime.Now }";
  10. }
  11. }
  12.  
  13. //Index.cshtml,直接输出后端的Message属性信息,也这是Razor的优势,使用页面的编码方式更简单高效。
  14. @page
  15. @using RazorPagesIntro.Pages
  16. @model IndexModel
  17.  
  18. <h2>Separate page model</h2>
  19. <p>
  20. @Model.Message
  21. </p>

  1.4 页面url路径

    URL路径是与页面的关联,由页面在文件系统中的位置决定,下表显示了Razor Page路径和匹配的URL:

文件路径 访问网址
/Pages/Index.cshtml /     or     /Index
/Pages/Contact.cshtml /Contact
/Pages/Store/Contact.cshtml /Store/Contact
/Pages/Store/Index.cshtml /Store  or  /Store/Index

二. 完整示例介绍

  

  2.1 安装EF数据提供程序

    这里使用内存数据库Microsoft.EntityFrameworkCore.InMemory,Entity Framework Core 和内存数据库一起使用, 这对测试非常有用。

  1.     PM> Install-Package Microsoft.EntityFrameworkCore.InMemory

    

  2.2 新建数据模型类(POCO )和EF上下文类 

  1. public class Customer
  2. {
  3. public int Id { get; set; }
  4.  
  5. //保存不能为空,字符长度小于100
  6. [Required, StringLength()]
  7. public string Name { get; set; }
  8. }
  9.  
  10. public class AppDbContext : DbContext
  11. {
  12. public AppDbContext(DbContextOptions options)
  13. : base(options)
  14. {
  15. }
  16.  
  17. public DbSet<Customer> Customers { get; set; }
  18. }

  2.3 启动类关键代码

  1. public class Startup
  2. {
  3. public IHostingEnvironment HostingEnvironment { get; }
  4.  
  5. public void ConfigureServices(IServiceCollection services)
  6. {
  7. // 使用内存数据库
  8. services.AddDbContext<AppDbContext>(options =>
  9. options.UseInMemoryDatabase("name"));
  10. services.AddMvc();
  11. }
  12.  
  13. public void Configure(IApplicationBuilder app)
  14. {
  15. app.UseMvc();
  16. }
  17. }

  2.4 新增页 Pages/Create

  1. @page
  2. @model StudyRazorDemo.Pages.CreateModel
  3. @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
  4. <html>
  5. <body>
  6. <p>
  7. Enter your name.
  8. </p>
  9. <div asp-validation-summary="All"></div>
  10. <form method="POST">
  11. <!-- 这里的Customer对象来自后端-->
  12. <div>Name: <input asp-for="Customer.Name" /></div>
  13. <input type="submit" />
  14. </form>
  15. </body>
  16. </html>
  1. public class CreateModel : PageModel
  2. {
  3. private readonly AppDbContext _db;
  4.  
  5. public CreateModel(AppDbContext db)
  6. {
  7. _db = db;
  8. }
  9.  
  10. //模型绑定,通过绑定使用相同的属性显示窗体字段<input asp-for="Customer.Name" />来减少代码,并接受输入,是双向绑定。
  11. [BindProperty]
  12. public Customer Customer { get; set; }
  13.  
  14. public async Task<IActionResult> OnPostAsync()
  15. {
  16. //验证Customer对象属性值
  17. if (!ModelState.IsValid)
  18. {
  19. return Page();
  20. }
  21.  
  22. //添加到EF上下文,再保存到内存数据库
  23. _db.Customers.Add(Customer);
  24. await _db.SaveChangesAsync();
  25.  
  26. // 重定向到index主页
  27. return RedirectToPage("/Index");
  28. }
  29. }

  点击提交后,cs后端的Customer对象将自动绑定来自前端转来的值,如下图所示:

  

  2.5 查询主页Pages/Index 关键代码

  1. <form method="post">
  2. <table class="table">
  3. <thead>
  4. <tr>
  5. <th>ID</th>
  6. <th>Name</th>
  7. </tr>
  8. </thead>
  9. <tbody>
  10. <!--Customers集合对象来自cs后端 -->
  11. @foreach (var contact in Model.Customers)
  12. {
  13. <tr>
  14. <td>@contact.Id</td>
  15. <td>@contact.Name</td>
  16. <td>
  17. <a asp-page="./Edit" asp-route-id="@contact.Id">edit</a>
  18.  
  19. <button type="submit" asp-page-handler="delete"
  20. asp-route-id="@contact.Id">
  21. delete
  22. </button>
  23. </td>
  24. </tr>
  25. }
  26. </tbody>
  27. </table>
  28. <a asp-page="./Create">Create</a>
  29. </form>
  1. public IList<Customer> Customers { get; private set; }
  2.  
  3. //代替OnGet方法
  4. public async Task OnGetAsync()
  5. {
  6. //异步获取数据,EF上下文不跟踪该集合对象
  7. Customers = await _db.Customers.AsNoTracking().ToListAsync();
  8. }

    所有asp- 开头的都是TagHelper内置标记,查询如下图所示:

  2.6 修改页Pages/Edit关键代码

    在主页中(<a asp-page="./Edit" asp-route-id="@contact.Id">edit</a> )是导航到编辑页。例如:http://localhost:5000/Edit/1。

    第一行包含 @page "{id:int}" 指令,是用来路由约束,如果页面请求未包含可转换为 int 的路由数据,则运行时返回 HTTP 404。若要使 ID可选,请将 ? 追加到路由约束( @page "{id:int?}" )

@page "{id:int}"
@model StudyRazorDemo.Pages.EditModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<h1>Edit Customer - @Model.Customer.Id</h1>

  1. <form method="post">
  2. <!--验证失败时,提示所有错误信息 -->
  3. <div asp-validation-summary="All"></div>
  4.  
  5. <input asp-for="Customer.Id" type="hidden" />
  6. <div>
  7. <label asp-for="Customer.Name"></label>
  8. <div>
  9. <input asp-for="Customer.Name" />
  10.  
  11. <!--后端验证Name,当失败时提示错误信息 -->
  12. <span asp-validation-for="Customer.Name"></span>
  13. </div>
  14. </div>
  15.  
  16. <div>
  17. <button type="submit">Save</button>
  18. </div>
  19. </form>
  1. [BindProperty]
  2. public Customer Customer { get; set; }
  3.  
  4. public async Task<IActionResult> OnGetAsync(int id)
  5. {
  6. Customer = await _db.Customers.FindAsync(id);
  7.  
  8. if (Customer == null)
  9. {
  10. return RedirectToPage("/Index");
  11. }
  12. return Page();
  13. }
  14.  
  15. public async Task<IActionResult> OnPostAsync()
  16. {
  17. if (!ModelState.IsValid)
  18. {
  19. return Page();
  20. }
  21.  
  22. _db.Attach(Customer).State = EntityState.Modified;
  23.  
  24. try
  25. {
  26. await _db.SaveChangesAsync();
  27. }
  28. catch (DbUpdateConcurrencyException)
  29. {
  30. throw new Exception($"Customer {Customer.Id} not found!");
  31. }
  32.  
  33. return RedirectToPage("/Index");
  34. }

    通过ID来修改数据,如下图所示:

  2.7 删除 Pages/index

    删除动作是在index页面完成。使用处理事件asp-page-handler="delete" 来指定后端的action 为delete方法处理。 按照约定,方法命名为: OnPost[handler]Async ,方法参数为 asp-route-id传来的值。

  1. /// <summary>
  2. /// index后端,根据ID删除
  3. /// </summary>
  4. /// <param name="id"></param>
  5. /// <returns></returns>
  6. public async Task<IActionResult> OnPostDeleteAsync(int id)
  7. {
  8. var contact = await _db.Customers.FindAsync(id);
  9.  
  10. if (contact != null)
  11. {
  12. _db.Customers.Remove(contact);
  13. await _db.SaveChangesAsync();
  14. }
  15.  
  16. return RedirectToPage();
  17. }

  

 参考文献

  详细的razor教程

   razor 页面介绍

  

asp.net core系列 39 Web 应用Razor 介绍与详细示例的更多相关文章

  1. asp.net core系列 40 Web 应用MVC 介绍与详细示例

    一. MVC介绍 MVC架构模式有助于实现关注点分离.视图和控制器均依赖于模型. 但是,模型既不依赖于视图,也不依赖于控制器. 这是分离的一个关键优势. 这种分离允许模型独立于可视化展示进行构建和测试 ...

  2. asp.net core系列 39 Razor 介绍与详细示例

    原文:asp.net core系列 39 Razor 介绍与详细示例 一. Razor介绍 在使用ASP.NET Core Web开发时, ASP.NET Core MVC 提供了一个新特性Razor ...

  3. asp.net core 系列 18 web服务器实现

    一. ASP.NET Core Module 在介绍ASP.NET Core Web实现之前,先来了解下ASP.NET Core Module.该模块是插入 IIS 管道的本机 IIS 模块(本机是指 ...

  4. asp.net core 系列 16 Web主机 IWebHostBuilder

    一.概述 在asp.net core中,Host主机负责应用程序启动和生存期管理.host主机包括Web 主机(IWebHostBuilder)和通用主机(IHostBuilder).Web 主机是适 ...

  5. asp.net core系列 44 Web应用 布局

    一.概述 MVC的视图与Razor页面经常共享视觉和程序元素,通过使用布局来完成,布局还可减少重复代码.本章演示了以下内容的操作方法:(1)使用通用布局,(2)自定义布局,(3) 共享指令,(4)在呈 ...

  6. asp.net core系列 43 Web应用 Session分布式存储(in memory与Redis)

    一.概述 HTTP 是无状态的协议. 默认情况下,HTTP 请求是不保留用户值或应用状态的独立消息. 本文介绍了几种保留请求间用户数据和应用状态的方法.下面以表格形式列出这些存储方式,本篇专讲Sess ...

  7. asp.net core系列 41 Web 应用 MVC视图

    一.MVC视图 在Web开发的MVC和Razor中,都有使用视图,在Razor中称为"页"..cshtml视图是嵌入了Razor标记的HTML模板. Razor 标记使用C#代码, ...

  8. asp.net core系列 42 Web 应用 分部视图

    一.分部视图 对于MVC 视图和 Razor Pages 页面,都有分部视图功能.通常将 MVC 视图和 Razor Pages 页面统称为“标记文件”,下面会常提到该名词.使用分部视图的优势包括:( ...

  9. asp.net core系列 67 Web压力测试工具WCAT

    一.介绍 最近搭建了一套CQRS框架,需要在投入开发前,进行必要的压力测试.Web Capacity Analysis Tool  (Wcat)是一种轻量级HTTP负载生成工具,主要用于衡量受控环境中 ...

随机推荐

  1. 在vue-cli3中优雅的使用 icon

    首先我们得有图标 这里我们从网上下载svg文件或者UI给你导出svg文件 我们在src 文件下新建一个放置svg 文件 的文件夹 @/src/icons.将所有 icon 放在这个文件夹下. 创建 i ...

  2. (六)read读取控制台输入

    1.基本语法 read(选项)(参数) 选项: -p:指定读取值时的提示符: -t:指定读取值时等待的时间(秒). 参数 变量:指定读取值的变量名 2.案例实操 (1)提示7秒内,读取控制台输入的名称 ...

  3. 网络对抗技术 20165220 Exp6 信息搜集与漏洞扫描

    网络对抗技术 20165220 Exp6 信息搜集与漏洞扫描 实验任务 (1)各种搜索技巧的应用 (2)DNS IP注册信息的查询 (3)基本的扫描技术:主机发现.端口扫描.OS及服务版本探测.具体服 ...

  4. [BZOJ1047][HAOI2007]理想的正方形(RMQ+DP)

    题意 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 思路 RMQ求 再DP 代码 #include<cstdio> #i ...

  5. 我在B站投稿啦、、、

    我在B站投稿啦....欢迎评论交流... https://www.bilibili.com/video/av31539882/  怎样激活Win10系统修改windows系统账户的名称-mp4 外链: ...

  6. Java工作原理:JVM,内存回收及其他

    JAVA虚拟机系列文章 http://developer.51cto.com/art/201001/176550.htm Java语言引入了Java虚拟机,具有跨平台运行的功能,能够很好地适应各种We ...

  7. Windows 查询端口占用

    1.找到端口的进程ID(PID)(例如:8080) Windows系统: netstat -ao | find " Windows以外的其他平台: lsof -i: 2.杀死你找到的进程ID ...

  8. FCC(ES6写法) Symmetric Difference

    创建一个函数,接受两个或多个数组,返回所给数组的 对等差分(symmetric difference) (△ or ⊕)数组. 给出两个集合 (如集合 A = {1, 2, 3} 和集合 B = {2 ...

  9. RabbitMQ in Action (2): Running and administering Rabbit

    Server management the Erlang node and the Erlang application Starting nodes multiple Erlang applicat ...

  10. rem布局完成响应式开发,通俗且详细的原理解析和代码实现

    一.rem布局基本原理 原理:rem可以理解为一个长度单位,单位rem的值等于网页font-size的值.如果网页的字体大小为默认值16px,那么1rem就等于16px,0.5rem等于8px. 根据 ...