作为.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框架,您可能会看到一些巨大的控制器类,其中包含许多不同的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 databaseusing (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 databaseusing (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的真正美丽是它的简单。
参考:
Introduction to Razor Pages in ASP.NET Core
.NET Core 2.0 Changes – 4 Key Things to Know
相关文章:
.NET Core 2.0 正式发布信息汇总
.NET Standard 2.0 特性介绍和使用指南
.NET Core 2.0 的dll实时更新、https、依赖包变更问题及解决
.NET Core 2.0 特性介绍和使用指南
Entity Framework Core 2.0 新特性
体验 PHP under .NET Core
.NET Core 2.0使用NLog
升级项目到.NET Core 2.0,在Linux上安装Docker,并成功部署
解决Visual Studio For Mac Restore失败的问题
ASP.NET Core 2.0 特性介绍和使用指南
.Net Core下通过Proxy 模式 使用 WCF
.NET Core 2.0 开源Office组件 NPOI
原文地址:http://www.cnblogs.com/tdfblog/p/asp-net-razor-pages-vs-mvc.html
.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注