大多数人,都低估了编程学习的难度,而高估了自己的学习能力和毅力。
当前系列: ASP.NET 修改讲义

要不要学?

RazorPages Application(按微软官方文档称呼)是微软

  • 是微软主推的
  • 基于.NET core和

最前沿的ASP.NET开发技术。

和ASP.NET core MVC就一个“模式架构”(MVVM)的区别。


新建项目

演示:新建一个RazorPage(Web App)项目


MVC core
没有Controller和Views(以及Models),只有Pages 文件夹

里面有成对的:

  • .cshtml:razor页面
  • .cshtml.cs:razor页面后台处理

Startup.cs中:

services.AddRazorPages();
endpoints.MapRazorPages();



Route

终点是“page”:声明了@page的.cshtml


PS:不是所有.cshtml文件都要/能声明@page,比如:

  • Layout中不能再声明@page,因为内容页里面已经声明了@page了。

  • ViewComponent中使用的view不能声明@page,因为它不能作为Http请求的Handler


默认

ASP.NET默认按以下规则,将HTTP请求导向Pages文件夹下的.cshtml页面:
URL Path 文件夹结构
根目录:/
Pages
子目录,如:/Blog Pages下的子文件夹,如:Pages\Blog
最后一级目录/文件,如:/Blog/Single
.cshtml文件,如:如:Pages\Blog\Single.cshtml

大体上,和静态网站的处理相似,只是:

  • 以Pages文件夹作为根目录
  • 去掉了.cshtml文件后缀名

另外,Index.cshtml 可以省略,即 /Blog/Index 和 /Blog 是一样的。

自定义

比如,让:/LogOn,转到:/Log/On.cshtml

ASP.NET提供了两种方式:

页面指定

即在.cshtml页面的@page声明后添加一个可以该Page可以匹配的路径。

比如,在/Log/On.cshtml的@page后添加:

@page "/LogOn"

注意

  1. /LogOn需要被引号""包裹。
  2. 不要漏掉了斜杠(/),否则就不是修改是“添加”(append)了 (在只是添加route data时有用)
    @page "{id}"

AddPageRoute()

我们还可以在startup.cs中修改:

    services.AddRazorPages()
        .AddRazorPagesOptions(opt =>
        {
            opt.Conventions.AddPageRoute("/Log/On", "/LogOn");
        });

AddPageRoute()方法向ASP.NET添加了一条route规则,两个URL Path格式的参数:

  • 第一个参数pageName,代表使用默认route规则匹配该URL能获得的Page
  • 第二个参数route:代表该自定义route规则适用的URL Path

或者,带上route data:

option.Conventions.AddPageRoute("/Article/Single", "/Article/{id}");


PageModel

.cshtml相关语法和之前一样,只有一点除外,获取RouteData:

@PageContext.RouteData.Values["id"]

创建和引入

在创建Razor页面时的时候,默认会生成相应的PageModel。

演示:在.cshtml文件中,有这样的代码:

@model Demo.Pages.RegisterModel

在RegisterModel上F12转到定义,可以知道RegisterModel其实是一个类,继承自PageModel。

注意其命名规范:类名同Page名,后加Model后缀

razor页面也可以没有model声明,ASP.NET直接输出.cshtml文件编译后的HTML内容。

此外,注意:组合之后的page可以有多个@model声明,但只能有一个@page声明

Handler Methods

在razor页面被添加的时候,其PageModel中就自动包含了一个OnGet()方法,用于处理HTTP GET请求。

PageModel根据 HTTP请求的方式(request methods)来确定调用方法:On+RequestMethod(),所以除了OnGet()方法,还有OnPost()方法等:这些都被称之为handler methods。

注意一个PageModel中:

  • 可以同时有OnGet()和OnPost()方法,但
  • 可以有多个OnGet()方法(或者多个OnPost()方法等),用参数重载区分也不行(会运行时错误)
  • OnGet()和OnPost()用带参数

方法体

在handler methods中,因为继承了PageModel,所以可以调用PageModel的一些常用属性,如:

  • Request:Http请求相关信息,常用的有:Header/Body、Cookies、Form/Query、Path、Schema等
  • Response:返回客户端的相应信息,常用的有:Header/Body、Cookies、StatusCode等
  • ViewData:存储页面(View)所需要的数据(Data)
  • RouteData:
  • HttpContext:当前请求的上下文信息,除了Request和Response,还有Connection、Session、WebSocket等有用信息
  • ……

返回值

他们既可以返回void,也可以返回IActionResult(PageResult)——通过调用PageModel中定义的方法,比如:

  • Page():等于return void 
  • RedirectToPage(),用于重定向到某一个页面。
  • Redirect():可接受绝对或相对的url为参数

没有Json()方法,所以只能:

public JsonResult OnGet()    //推荐,可读性更高
{
    return new JsonResult(new
    {
        Name = "fg", age=18

PS:IActionResult 的继承结构

  1. 普通HTML页面:PageResult / ViewResult :
  2. 重定向:RedirectResult / RedirectToActionResult  /  RedirectToPageResult  /  RedirectToRouteResult 
  3. 部分页:PartialViewResult 
  4. Json格式数据:JsonResult 
  5. 文件:FileResult 
  6. ……

Model传值

PageModel中可以声明属性,然后其对应(用@model声明)的.cshtml中就可以(和MVC一样)直接@Model.使用。

注意:是通过Page()参数传!F12演示:Page()就没有方法重载。

ViewData也一样,但没有ViewBag。

MVVM模式

复习

#体会#:PageModel就对应ViewModel,居于核心地位,实现数据的双向绑定


Model绑定

前端传来的数据,一样可以自动绑定,只是绑定到PageModel的属性而已。

[BindProperty(ies)]

但需要为属性添加特性[BindProperty]:
[BindProperty]
public string UserName { get; set; }    /*UserName进行了绑定,能够绑定前台传值*/
public string Password { get; set; }    /*Password没有绑定,不能够绑定前台传值*/

或者在PageModel上声明[BindProperties]:

[BindProperties]
public class RegisterModel : PageModel

让ReigisterModel里的所有属性自动绑定。

SupportGet

Model数据绑定默认发生在POST请求中。

如果要在GET请求中进行绑定(注意区分FromBody),就需要:

[BindProperty(SupportsGet = true)]
public string Prepage { get; set; }


Filter

总体来说,和MVC差距不大,都是:

  • 继承基类:(注意引用的程序集应该是AspnetCore.MVC,不能是api/FW
    public class ContextPerRequest : ResultFilterAttribute
    或者实现接口:
    public class NeedLogOn : Attribute, IAuthorizationFilter
    
  • 全局注册(在service),
    services.AddRazorPages()
        //不是.AddRazorPagesOptions()
        .AddMvcOptions(opt =>
    {
        opt.Filters.Add(new ContextPerRequest());
    或者标记特性(在PageModel)
    [NeedLogOn]    //只能在PageModel上
    public class IndexModel : PageModel

只是RazorPages还可以在PageModel中通过override实现,执行顺序:

public override void OnPageHandlerSelected(PageHandlerSelectedContext context){}
public override void OnPageHandlerExecuting(PageHandlerExecutingContext context){}
public override void OnPageHandlerExecuted(PageHandlerExecutedContext context){}

当然,这些override方法只能作用于当前PageModel。


作业

任何一个页面,
  1. 点击导航栏“登录”和“注册”,跳转到登录/注册页面;完成登录和注册之后能返回之前页面
  2. 点击导航栏“退出登录”(/LogOff):
  • 如果当前页面不需要登录,只刷新不跳转,
  • 否则跳转到登录页面……

提示:

  • 用url参数记住当前页面,在重定向的时候才有目标页
  • 如果已经在/LogOn页面,再点击注册页面,会不会有bug?

学习笔记
源栈学历
大多数人,都低估了编程学习的难度,而高估了自己的学习能力和毅力。

作业

觉得很 ,不要忘记分享哟!

任何问题,都可以直接加 QQ群:273534701

在当前系列 ASP.NET 中继续学习:

多快好省!前端后端,线上线下,名师精讲

  • 先学习,后付费;
  • 不满意,不要钱。
  • 编程培训班,我就选源栈

更多了解 加:

QQ群:273534701

答疑解惑,远程debug……

B站 源栈-小九 的直播间

写代码要保持微笑 (๑•̀ㅂ•́)و✧

公众号:源栈一起帮

二维码