ASP.NET?Core中Razor頁(yè)面與MVC區(qū)別介紹
作為.NET Core 2.0發(fā)行版的一部分,還有一些ASP.NET的更新。其中之一是添加了一個(gè)新的Web框架來創(chuàng)建“頁(yè)面”,而不需要復(fù)雜的ASP.NET MVC。新的Razor頁(yè)面是一個(gè)比較簡(jiǎn)單的MVC框架版本,在某些方面是老的“.aspx” WebForms的演變。
在本文中,我們將介紹使用ASP.NET Razor頁(yè)面和MVC的一些細(xì)節(jié)。
- Razor頁(yè)面基礎(chǔ)知識(shí)
- ASP.NET MVVM vs MVC
- Razor頁(yè)面的優(yōu)點(diǎn)和缺點(diǎn)
- 使用Handlers實(shí)現(xiàn)多個(gè)GET、POST Action方法
- 為什么您應(yīng)該使用Razor Pages
- ASP.NET Razor頁(yè)面與MVC代碼的區(qū)別
基礎(chǔ)知識(shí):什么是ASP.NET Razor頁(yè)面?
Razor頁(yè)面與ASP.NET MVC開發(fā)使用的視圖組件非常相似,它們具有所有相同的語(yǔ)法和功能。
最關(guān)鍵的區(qū)別是模型和控制器代碼也包含在Razor頁(yè)面中。它更像是一個(gè)MVVM(Model-View-ViewModel)框架,它支持雙向數(shù)據(jù)綁定,更簡(jiǎn)單的開發(fā)體驗(yàn),具有獨(dú)立的關(guān)注點(diǎn)。
下面是一個(gè)Razor頁(yè)面最基本的示例,在@functions
塊中內(nèi)嵌代碼,不過推薦將PageModel
代碼放在一個(gè)單獨(dú)的文件中。這更像是我們?cè)贏SP.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>
我們現(xiàn)在兩個(gè)選擇:ASP.NET MVVM 或 MVC
我們現(xiàn)在有兩個(gè)選擇,一個(gè)MVC,另一個(gè)是MVVM框架。我不打算介紹MVC vs MVVM的所有細(xì)節(jié)。在這篇文章中用一些例子很詳細(xì)說明了這一點(diǎn)。MVVM框架最關(guān)注的是數(shù)據(jù)模型的雙向綁定。
MVC適用于具有大量動(dòng)態(tài)服務(wù)器視圖、單頁(yè)應(yīng)用程序、REST API和AJAX調(diào)用的應(yīng)用程序。Razor頁(yè)面非常適用于只讀或執(zhí)行基本數(shù)據(jù)輸入的簡(jiǎn)單頁(yè)面。
MVC最近在大多數(shù)編程語(yǔ)言的Web應(yīng)用程序中非常流行,但是它也有其利弊。ASP.NET WebForms被設(shè)計(jì)為一個(gè)MVVM解決方案,您可以認(rèn)為Razor頁(yè)面是WebForms的演變。
Razor頁(yè)面的優(yōu)點(diǎn)和缺點(diǎn)
根據(jù)我在使用新的Razor頁(yè)面過程中,下面是我總結(jié)的利弊以及我是如何看待使用它們。
優(yōu)點(diǎn):更有條理
我不知道您,但是我第一次使用ASP.NET MVC,花了很多時(shí)間試圖弄清楚它是如何工作的。命名規(guī)則和動(dòng)態(tài)創(chuàng)建路由導(dǎo)致了很多我不習(xí)慣的規(guī)則。事實(shí)上,從路徑“/Home/”到HomeController.Index()
,它從“Views\Home\Index.cshtml”中加載一個(gè)視圖文件,在剛開始使用時(shí)覺得很神奇。
Razor頁(yè)面更有條理。您有一個(gè)Razor視圖和后臺(tái)代碼文件,就像WebForms一樣,不像與MVC對(duì)應(yīng)的控制器、視圖和模型存放在不同目錄中具有單獨(dú)的文件。
MVC項(xiàng)目和Razor頁(yè)面項(xiàng)目比較(將在本文后面介紹更多的代碼差異)。
MVC與Razor頁(yè)面文件比較
優(yōu)點(diǎn):?jiǎn)我回?zé)任
如果您以前曾經(jīng)使用過MVC框架,您可能會(huì)看到一些巨大的控制器類,其中包含許多不同的Action。它們就像一種隨著時(shí)間的推移而增加的病毒。
使用Razor頁(yè)面,每個(gè)頁(yè)面都是獨(dú)立的,視圖和代碼組織在一起,這遵循單一責(zé)任原則。
使用Handlers實(shí)現(xiàn)多個(gè)GET、POST Action
默認(rèn)情況下,Razor頁(yè)面設(shè)計(jì)為具有單個(gè)OnGetAsync
和OnPostAsync
Action方法;如果您想在單個(gè)頁(yè)面中具有不同的Action,則需要使用所謂的Handler。如您的頁(yè)面有AJAX回調(diào)、多個(gè)表單提交或其它場(chǎng)景,則需要使用它。
例如,如果您使用Kendo Grid并希望通過AJAX調(diào)用加載Grid數(shù)據(jù),則需要使用Handler來處理該AJAX調(diào)用。任何類型的單頁(yè)面應(yīng)用程序?qū)⑹褂么罅縃andler,或者您將所有這些AJAX調(diào)用指向MVC控制器。
我在頁(yè)面中添加了一個(gè)名為OnGetHelloWorldAsync()
的方法,我們?cè)撛趺凑{(diào)用它?
從我的研究來看, 調(diào)用Handler有三種不同的方式:
- Querystring – 示例:“/managepage/2177/?handler=helloworld”
- 為視圖中的定義路由:
@page"{handler?}"
,然后在Url中包括“/helloworld” - 在視圖中定義提交按鈕 - 示例:<input type="submit" asp-page-handler="JoinList" value="Join" />
可以在這里了解更多有關(guān)單頁(yè)面多個(gè)Handlers 的方式。
為什么您應(yīng)該使用Razor頁(yè)面的!
Razor頁(yè)面是網(wǎng)頁(yè)應(yīng)用程序中的完美解決方案,我可能提出一個(gè)爭(zhēng)議。它一目了然,你的應(yīng)用程序中的任何HTML“頁(yè)面”都是真實(shí)的頁(yè)面。目前,MVC Action 可以返回HTML視圖、JSON、文件或任何內(nèi)容。使用Razor頁(yè)面將頁(yè)面加載和AJAX回調(diào)的服務(wù)之間強(qiáng)制分離。
想想,這種強(qiáng)制分離解決了很多問題。
Razor Page | MVC |
---|---|
HTML Views | REST API calls, SOA |
這將阻止MVC控制器包含大量的Action,MVC應(yīng)用程序中的Action混合了不同的“頁(yè)面”,而且還包含AJAX回調(diào)和其它功能。
當(dāng)然,我還沒有實(shí)際中使用這種開發(fā)方式,這可能是失敗,也可能是成功的,只有時(shí)間才能告訴社區(qū)如何使用Razor頁(yè)面。
ASP.NET Razor頁(yè)面與MVC的代碼比較
作為Razor頁(yè)面的一部分,我在MVC和Razor頁(yè)面中構(gòu)建了一個(gè)非常簡(jiǎn)單Form表單。讓我們來看看之間的代碼。它只有一個(gè)文本框和提交按鈕。
這是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控制器(數(shù)據(jù)模型是PageClass,只有兩個(gè)屬性,很簡(jiǎn)單)。
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); } }
現(xiàn)在我們來比較一下Razor頁(yè)面。
Razor 頁(yè)面:
@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,也稱之為后臺(tái)代碼:
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(); } }
差異解密
兩者之間的代碼幾乎相同,以下是主要的區(qū)別:
- MVC視圖代碼部分完全相同,除了Razor頁(yè)面頂上的
@page
; - ManagePageModel具有
OnGetAsync
和OnPostAsync
方法,取代了MVC控制器中兩個(gè)“ManagePage” Action; - ManagePageModel包含之前單獨(dú)在
PageClass
中的兩個(gè)屬性。
在MVC中HTTP POST請(qǐng)求,將對(duì)象傳遞給MVC的Action(例如ManagePage(int id,PageClass page)
);使用Razor頁(yè)面,可以使用數(shù)據(jù)雙向綁定。為了讓Razor頁(yè)面正確地使用雙向數(shù)據(jù)綁定,我兩個(gè)屬性(PageDataID
、Title
)使用了[BindProperty]
標(biāo)記。
總結(jié)
我真的很喜歡Razor頁(yè)面,可以看到在我正在開發(fā)的ASP.NET Core項(xiàng)目中使用它們。我喜歡Razor頁(yè)面的原因是應(yīng)用程序中的真實(shí)頁(yè)面,并使用MVC實(shí)現(xiàn)所有AJAX/REST API。我承認(rèn)還有其它功能,Razor頁(yè)面實(shí)現(xiàn)不了。好消息是MVC是超級(jí)靈活的,但這也使得它變得更加復(fù)雜。Razor Pages的真正美麗是它的簡(jiǎn)單。
到此這篇關(guān)于ASP.NET Core中Razor頁(yè)面與MVC區(qū)別的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- ASP.NET Core中的Razor頁(yè)面實(shí)現(xiàn)路由功能
- ASP.NET?Core中Razor頁(yè)面的Handlers處理方法詳解
- ASP.NET?Core?Razor頁(yè)面用法介紹
- ASP.NET?Core中的Razor頁(yè)面介紹
- asp.net core razor自定義taghelper的方法
- ASP.NET Core 2.0中Razor頁(yè)面禁用防偽令牌驗(yàn)證
- 如何ASP.NET Core Razor中處理Ajax請(qǐng)求
- ASP.NET Core Razor 頁(yè)面路由詳解
- ASP.NET Core中的Razor頁(yè)面使用視圖組件
相關(guān)文章
asp.net和ajax實(shí)現(xiàn)智能搜索功能代碼
近來一直在開發(fā)股票模擬系統(tǒng),終于告一段落了,回想起來感慨很多。突然想應(yīng)該做點(diǎn)總結(jié)了,想來想去還是覺得通過寫點(diǎn)日志來把相關(guān)的知識(shí)點(diǎn)記錄下來,下面就我在項(xiàng)目中經(jīng)常用到的動(dòng)態(tài)提示搜索選項(xiàng)功能的實(shí)現(xiàn)。2010-03-03asp.net下一個(gè)賬號(hào)不允許多個(gè)用戶同時(shí)在線,重復(fù)登陸的代碼
asp.net下一個(gè)賬號(hào)不允許多個(gè)用戶同時(shí)在線,重復(fù)登陸的代碼,需要的朋友可以參考下。2010-10-10.NET?Core使用Autofac容器的DI依賴注入,IOC控制反轉(zhuǎn)及AOP切面編程
本文詳細(xì)講解了.NET?Core使用Autofac容器的DI依賴注入,IOC控制反轉(zhuǎn)及AOP切面編程,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02ASP.NET(VB)寫的后臺(tái)發(fā)送短信實(shí)現(xiàn)代碼
使用vb寫的后臺(tái)發(fā)送短信代碼,很實(shí)用的一項(xiàng)功能,感興趣的朋友可以了解下,或許對(duì)你學(xué)習(xí)asp.net vb有所幫助2013-02-02asp.net Web Service 接口大量數(shù)據(jù)傳輸解決方案
就管他叫“使用多線程分段獲取大量數(shù)據(jù)方法”吧。假定我們的需求是,通過Web Service獲取10W條訂單,我的解決方案是 分成10個(gè)線程每個(gè)線程傳輸1W條訂單分段獲取2010-04-04ASP.NET向Javascript傳遞變量?jī)煞N實(shí)現(xiàn)方法
ASP.NET向Javascript傳遞變量?jī)煞N實(shí)現(xiàn)方法,需要的朋友可以參考下2012-12-12asp.net 錯(cuò)誤:0x8007000B 異常的解決方法
這篇文章主要介紹了asp.net 錯(cuò)誤:0x8007000B 異常的解決方法,需要的朋友可以參考下2015-01-01