ASP.NET Core Razor页面 vs MVC
作为.NET Core 2.0发行版的一部分,还有一些ASP.NET的更新。其中之一是添加了一个新的Web框架来创建“页面”,而不需要复杂的ASP.NET MVC。新的Razor页面是一个比较简单的MVC框架版本,在某些方面是老的“.aspx” WebForms的演变。
在本文中,我们将介绍使用ASP.NET Razor页面和MVC的一些细节。
- Razor页面基础知识
- ASP.NET MVVM vs MVC
- Razor页面的优点和缺点
- 使用Handlers实现多个GET、POST Action方法
- 为什么您应该使用Razor Pages
- ASP.NET Razor页面与MVC代码的区别
基础知识:什么是ASP.NET Razor页面?
Razor页面与ASP.NET MVC开发使用的视图组件非常相似,它们具有所有相同的语法和功能。
最关键的区别是模型和控制器代码也包含在Razor页面中。它更像是一个MVVM(Model-View-ViewModel)框架,它支持双向数据绑定,更简单的开发体验,具有独立的关注点。
下面是一个Razor页面最基本的示例,在@functions
块中内嵌代码,不过推荐将PageModel
代码放在一个单独的文件中。这更像是我们在ASP.NET WebForms文件中编写代码的方式。
@page
@model IndexModel
@using Microsoft.AspNetCore.Mvc.RazorPages
@functions {
public class IndexModel : PageModel
{
public string Message { get; private set; } = "In page model: ";
public void OnGet()
{
Message += $" Server seconds { DateTime.Now.Second.ToString() }";
}
}
}
<h2>In page sample</h2>
<p>
@Model.Message
</p>
我们现在两个选择:ASP.NET MVVM 或 MVC
我们现在有两个选择,一个MVC,另一个是MVVM框架。我不打算介绍MVC vs MVVM的所有细节。在这篇文章中用一些例子很详细说明了这一点。MVVM框架最关注的是数据模型的双向绑定。
MVC适用于具有大量动态服务器视图、单页应用程序、REST API和AJAX调用的应用程序。Razor页面非常适用于只读或执行基本数据输入的简单页面。
MVC最近在大多数编程语言的Web应用程序中非常流行,但是它也有其利弊。ASP.NET WebForms被设计为一个MVVM解决方案,您可以认为Razor页面是WebForms的演变。
Razor页面的优点和缺点
我(Matt Watson)一直在做ASP.NET开发大约15年了,精通所有的ASP.NET框架。根据我在使用新的Razor页面过程中,下面是我总结的利弊以及我是如何看待使用它们。
优点:更有条理,更少的“潜规则”
我不知道您,但是我第一次使用ASP.NET MVC,花了很多时间试图弄清楚它是如何工作的。命名规则和动态创建路由导致了很多我不习惯的规则。事实上,从路径“/Home/”到HomeController.Index()
,它从“Views\Home\Index.cshtml”中加载一个视图文件,在刚开始使用时觉得很神奇。
Razor页面没有任何“潜规则”,文件更有条理。您有一个Razor视图和后台代码文件,就像WebForms一样,不像与MVC对应的控制器、视图和模型存放在不同目录中具有单独的文件。
MVC项目和Razor页面项目比较(将在本文后面介绍更多的代码差异)。
MVC与Razor页面文件比较
优点:单一责任
如果您以前曾经使用过MVC框架,您可能会看到一些巨大的控制器类,其中包含许多不同的Action。它们就像一种随着时间的推移而增加的病毒。
使用Razor页面,每个页面都是独立的,视图和代码组织在一起,这遵循单一责任原则。
使用Handlers实现多个GET、POST Action
默认情况下,Razor页面设计为具有单个OnGetAsync
和OnPostAsync
Action方法;如果您想在单个页面中具有不同的Action,则需要使用所谓的Handler。如您的页面有AJAX回调、多个表单提交或其它场景,则需要使用它。
例如,如果您使用Kendo Grid并希望通过AJAX调用加载Grid数据,则需要使用Handler来处理该AJAX调用。任何类型的单页面应用程序将使用大量Handler,或者您将所有这些AJAX调用指向MVC控制器。
我在页面中添加了一个名为OnGetHelloWorldAsync()
的方法,我们该怎么调用它?
从我的研究来看, 调用Handler有三种不同的方式:
- Querystring – 示例:“/managepage/2177/?handler=helloworld”
- 为视图中的定义路由:
@page"{handler?}"
,然后在Url中包括“/helloworld” - 在视图中定义提交按钮 - 示例:<input type="submit" asp-page-handler="JoinList" value="Join" />
可以在这里了解更多有关单页面多个Handlers 的方式。
为什么您应该使用Razor页面的!
Razor页面是网页应用程序中的完美解决方案,我可能提出一个争议。它一目了然,你的应用程序中的任何HTML“页面”都是真实的页面。目前,MVC Action 可以返回HTML视图、JSON、文件或任何内容。使用Razor页面将页面加载和AJAX回调的服务之间强制分离。
想想,这种强制分离解决了很多问题。
Razor Page | MVC |
---|---|
HTML Views | REST API calls, SOA |
这将阻止MVC控制器包含大量的Action,MVC应用程序中的Action混合了不同的“页面”,而且还包含AJAX回调和其它功能。
当然,我还没有实际中使用这种开发方式,这可能是失败,也可能是成功的,只有时间才能告诉社区如何使用Razor页面。
ASP.NET Razor页面与MVC的代码比较
作为Razor页面的一部分,我在MVC和Razor页面中构建了一个非常简单Form表单。让我们来看看之间的代码。它只有一个文本框和提交按钮。
这是MVC视图:
@model RazorPageTest.Models.PageClass
<form asp-action="ManagePage">
<div class="form-horizontal">
<h4>Client</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="PageDataID" />
<div class="form-group">
<label asp-for="Title" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</form>
这是MVC控制器(数据模型是PageClass,只有两个属性,很简单)。
public class HomeController : Controller
{
public IConfiguration Configuration;
public HomeController(IConfiguration config)
{
Configuration = config;
}
public async Task<IActionResult> ManagePage(int id)
{
PageClass page;
using (var conn = new SqlConnection(Configuration.GetConnectionString("contentdb")))
{
await conn.OpenAsync();
var pages = await conn.QueryAsync<PageClass>("select * FROM PageData Where PageDataID = @p1", new { p1 = id });
page = pages.FirstOrDefault();
}
return View(page);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ManagePage(int id, PageClass page)
{
if (ModelState.IsValid)
{
try
{
//Save to the database
using (var conn = new SqlConnection(Configuration.GetConnectionString("contentdb")))
{
await conn.OpenAsync();
await conn.ExecuteAsync("UPDATE PageData SET Title = @Title WHERE PageDataID = @PageDataID", new { page.PageDataID, page.Title});
}
}
catch (Exception)
{
//log it
}
return RedirectToAction("Index", "Home");
}
return View(page);
}
}
现在我们来比较一下Razor页面。
Razor 页面:
@page "{id:int}"
@model RazorPageTest2.Pages.ManagePageModel
<form asp-action="ManagePage">
<div class="form-horizontal">
<h4>Manage Page</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="PageDataID" />
<div class="form-group">
<label asp-for="Title" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</form>
这是Razor PageModel,也称之为后台代码:
public class ManagePageModel : PageModel
{
public IConfiguration Configuration;
public ManagePageModel(IConfiguration config)
{
Configuration = config;
}
[BindProperty]
public int PageDataID { get; set; }
[BindProperty]
public string Title { get; set; }
public async Task<IActionResult> OnGetAsync(int id)
{
using (var conn = new SqlConnection(Configuration.GetConnectionString("contentdb")))
{
await conn.OpenAsync();
var pages = await conn.QueryAsync("select * FROM PageData Where PageDataID = @p1", new { p1 = id });
var page = pages.FirstOrDefault();
this.Title = page.Title;
this.PageDataID = page.PageDataID;
}
return Page();
}
public async Task<IActionResult> OnPostAsync(int id)
{
if (ModelState.IsValid)
{
try
{
//Save to the database
using (var conn = new SqlConnection(Configuration.GetConnectionString("contentdb")))
{
await conn.OpenAsync();
await conn.ExecuteAsync("UPDATE PageData SET Title = @Title WHERE PageDataID = @PageDataID", new { PageDataID, Title });
}
}
catch (Exception)
{
//log it
}
return RedirectToPage("/");
}
return Page();
}
}
差异解密
两者之间的代码几乎相同,以下是主要的区别:
- MVC视图代码部分完全相同,除了Razor页面顶上的
@page
; - ManagePageModel具有
OnGetAsync
和OnPostAsync
方法,取代了MVC控制器中两个“ManagePage” Action; - ManagePageModel包含之前单独在
PageClass
中的两个属性。
在MVC中HTTP POST请求,将对象传递给MVC的Action(例如ManagePage(int id,PageClass page)
);使用Razor页面,可以使用数据双向绑定。为了让Razor页面正确地使用双向数据绑定,我两个属性(PageDataID
、Title
)使用了[BindProperty]
标记。
总结
我真的很喜欢Razor页面,可以看到在我正在开发的ASP.NET Core项目中使用它们。我喜欢Razor页面的原因是应用程序中的真实页面,并使用MVC实现所有AJAX/REST API。我承认还有其它功能,Razor页面实现不了。好消息是MVC是超级灵活的,但这也使得它变得更加复杂。Razor Pages的真正美丽是它的简单。
参考:
原文:《ASP.NET Razor Pages vs MVC: How Do Razor Pages Fit in Your Toolbox?》https://stackify.com/asp-net-razor-pages-vs-mvc/
翻译:Sweet Tang
本文地址:http://www.cnblogs.com/tdfblog/p/asp-net-razor-pages-vs-mvc.html
欢迎转载,请在明显位置给出出处及链接。
ASP.NET Core Razor页面 vs MVC的更多相关文章
- ASP.NET Core - Razor 页面简介
简介 随着ASP.NET Core 2 即将来临,最热门的新事物是Razor页面.在之前的一篇文章中,我们简要介绍了ASP.NET Core Razor 页面. Razor页面是ASP.NET Cor ...
- ASP.NET Core Razor页面禁用防伪令牌验证
在这篇短文中,我将向您介绍如何ASP.NET Core Razor页面中禁用防伪令牌验证. Razor页面是ASP.NET Core 2.0中增加的一个页面控制器框架,用于构建动态的.数据驱动的网站: ...
- ASP.NET Core - Razor 页面介绍
简介 随着ASP.NET Core 2 即将来临,最热门的新事物是Razor页面.在之前的一篇文章中,我们简要介绍了ASP.NET Core Razor 页面. Razor页面是ASP.NET Cor ...
- ASP.NET Core Razor 页面使用指南
ASP.NET Core Razor 页面作为 ASP.NET Core 2.0的一部分发布,它是基于页面的全新的Web开发框架.如果您想学习如何使用 ASP.NET Core Razor 页面,可以 ...
- Asp.Net Core Razor页面中使用echarts展示图形
Asp.Net Core Razor页面中使用echarts展示图形 要在Razor页面中使用echarts显示图形,主要问题点在于如何将数据传递给js文件. 1,下载安装echarts库文件 首先引 ...
- Asp.net core Razor 页面
创建asp.net core 空项目->MyWeb 修改Startup.cs启动文件添加Razor页面支持: public void ConfigureServices(IServiceColl ...
- ASP.Net Core Razor 页面路由
在服务器端 Web 应用程序框架中,其中非常重要的设计是开发人员如何将URL与服务器上的资源进行匹配,以便正确的处理请求.最简单的方法是将 URL 映射到磁盘上的物理文件,在 Razor 页面框架中, ...
- 4.将验证添加到 ASP.NET Core Razor 页面
向 Movie 模型添加了验证逻辑. 每当用户创建或编辑电影时,都会强制执行验证规则. 1.打开Movie.cs文件.DataAnnotations命名空间提供了一组内置的验证属性,这些属性以声明方式 ...
- C#编译器优化那点事 c# 如果一个对象的值为null,那么它调用扩展方法时为甚么不报错 webAPI 控制器(Controller)太多怎么办? .NET MVC项目设置包含Areas中的页面为默认启动页 (五)Net Core使用静态文件 学习ASP.NET Core Razor 编程系列八——并发处理
C#编译器优化那点事 使用C#编写程序,给最终用户的程序,是需要使用release配置的,而release配置和debug配置,有一个关键区别,就是release的编译器优化默认是启用的.优化代码 ...
随机推荐
- jdk和jre有什么区别?
简单的说JDK是面向开发人员使用的SDK,它提供了Java的开发环境和运行环境.SDK是Software Development Kit 一般指软件开发包,可以包括函数库.编译程序等. JDK就是Ja ...
- LinkedList源码浅析(jdk1.8)
LinkedList由双向链表实现的集合,因此可以从头或尾部双向循环遍历. LinkedList的操作都是对双向链表的操作,理解双向链表的数据结构就很容易理解LinkedList的实现. 双向链表由带 ...
- javascript事件轮询
JavaScript 运行机制详解:再谈Event Loop 一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么Ja ...
- python selenium自动化之-环境搭建
安装python和pip上述文章有介绍,在这里不在赘述.直接安装seleinum pip3 install selenium 安装完成以后, pip3 show selenium 显示 Name: s ...
- 【MySQL故障处理】 Seconds_Behind_Master= NULL Error_code: 1197
版本:mysql 5.6.32**错误描述:**```Error_code: 1197Last_Error: Worker 3 failed executing transaction '352aa3 ...
- 最小生成树之Prim算法和Kruskal算法
最小生成树算法 一个连通图可能有多棵生成树,而最小生成树是一副连通加权无向图中一颗权值最小的生成树,它可以根据Prim算法和Kruskal算法得出,这两个算法分别从点和边的角度来解决. Prim算法 ...
- [luogu P3384] 【模板】树链剖分 [树链剖分]
题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...
- input复选框操作的部分高频率使用代码
1. 获取单个checkbox选中项(三种写法): $("input:checkbox:checked").val() 或者 $("input:[type='checkb ...
- json-server mock数据
前言: 项目开发中,影响项目进程的常常是由于在前后端数据交互的开发流程中停滞,前端完成静态页面的开发后,后端迟迟未给到接口.而现在,我们就可以通过根据后端接口字段,建立一个REST风格的API接口,进 ...
- (转)JAVA新特征
Java线程:新特征-有返回值的线程 在Java5之前,线程是没有返回值的,常常为了“有”返回值,破费周折,而且代码很不好写.或者干脆绕过这道坎,走别的路了. 现在Java终于有可返回值的任务 ...