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框架,您可能會看到一些巨大的控制器類,其中包含許多不同的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回調的服務之間強制分離。
想想,這種強制分離解決了很多問題。
| 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跨平臺或掃描二維碼關注
總結
以上是生活随笔為你收集整理的ASP.NET Core Razor页面 vs MVC的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Orleans例子再进一步
- 下一篇: C#使用Xamarin开发可移植移动应用