Do You Kown Asp.Net Core -- Asp.Net Core 2.0 未來web開發新趨勢 Razor Page


Razor Page介紹

前言

    上周期待已久的Asp.Net Core 2.0提前發布了,一下子Net圈熱鬧了起來,2.0帶來了很多新的特性和新的功能,其中Razor Page引起我的關注,作為web程序員來說,Asp.Net下的任何web框架都會去特別關注,因為每次一個新的框架出來,意味着一次革命。此次的Razor Page是否能帶來不一樣的體驗呢,讓我們一起來看看吧。

什么是Razor Page

    我們都知道在Asp.Net MVC中,Razor是其一種視圖引擎。而今天我們介紹的Razor Page卻是一種web框架,它是一種簡化的MVC框架,如果你曾經做過WebForm的開發者,你會發現,Razor Page有點類似Web Form,一個page,一個class。

    大家或許會有疑惑,我們現在Asp.Net MVC已經很完善了,為何還需要出來一種新型的框架呢?在我看來,MVC確實已經足夠強大了,只是因為太強大了,卻變成了它的缺點。當我們的業務越來越龐大的時候,你是否覺得你的一個Controller內部已經凌亂不堪?當我們業務模塊划分越多的時候,你是否會為你的Model創建而頭疼呢?當我們創建一個新的View的時候,我們需要在MVC層增加1個View,1個Model,修改一個Controller,每當這個時候,我都會疑惑這不是違反Open-Closed Principle(對擴展開放,對修改關閉)了嘛!這個時候我會想起以前的webform,現在不需要了,我們有了Razor Page,一種更輕量級的MVC(我覺得更像MVVM)。

如何創建Razor Page

我們可以通過多種方式來創建Razor Page項目,最簡單的就是利用dotnet命令方式,當然我還是建議您使用Visual Studio 2017(宇宙最強的IDE)。要創建Razor Page,你需要先安裝.Net Core 2.0 SDK,如果要使用VS2017來創建,您還必須要更新到15.3版本以上

dotnet命令方式創建

打開cmd或者powershell工具,先檢查下你的dotnet 版本是否為2.0.0

dotnet –version

先通過命令,到你需要創建項目的目錄,我這里為E盤下demos目錄:cd e:\demos\RazorPageDemo1

dotnet new razor

輸入以上命令,你就已經創建了razorPage的項目了,這里說一下dotnet 2.0默認是自動restore的,你也可以通過--no-restore選項關閉。我們直接通過命令dotnet run 可以直接運行,看到的頁面應該跟之前mvc創建的類似。

輸入dir,我們看下生成了哪些:

image

跟之前mvc不同的是,我們不再看到model,view,controller目錄了,取而代之的是Pages目錄,這個就是我們的razor Page的主要工作目錄。

Visual Studio 2017創建Razor Page

用Visual Studio 2017創建是非常方便的(宇宙最強IDE),不過我們必須要先升級到15.3,升級之后選擇新建項目->.Net Core –> Asp.Net Core Web應用程序,接下來會彈出一個對話框,讓我們選擇模板類型:

image

多了好多模板,好興奮啊!我們在這里無法找到Razor Page,那是因為Razor Page已經變成默認的【Web應用程序模板】了,而傳統的MVC方式已經變成【Web應用程序(模型視圖控制器)】。選擇【Web應用程序模板】,點擊確定我們就完成創建了,通過Solution Explore,我們可以看到:

image

與命令方式創建的一致。

QuickStart Razor Page

Hello Razor Page

通過上節我們創建了Razor Page項目,直接通過dotnet run或者在vs中F5運行。上文中我們說到,Razor Page的項目中,我們的關注點都在Pages目錄下,在VS Explore中,我們看到在Index.cshtml的左邊有一個三角箭頭,點擊就會看到Index.cshtml.cs文件,是不是感覺回到了webform。我們看下代碼:

public class IndexModel : PageModel
{
    public void OnGet()
    {

    }
}

因為我們的Index頁面沒有綁定任何數據,所以這里基本上只繼承了PageModel,OnGet方法是個約定,查看mvc的源碼你會發現它會獲取On{handler}{Async}()。比如OnGet,它會在Get Index的時候被執行,我們可以通過這個約定進行數據綁定,這里知道下在Razor Page下HttpMethod也是一個handler,所以Razor Page的處理方式是通過handler進行的。

舉個例子,我們在IndexModel中添加一個String類型的屬性Message,在OnGet中進行賦值:

public void OnGet()
{
    Message = "this is a test!";
}

然后我們修改下Index.csthml:

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="row">
   Message : @Model.Message
</div>

運行下,如果我們在頁面上看到Message : this is a test!,說明賦值成功。

是不是很方便,一般我們的web基本上百分之八十在Get和Post,特別情況會出現其他HttpMethod,當然我們的RazorPage也支持,不過不建議。

現在來說PageModel就是一個Model,Action,HttpMethod的合體,對於Controller使用文件自己的路徑+文件名的方式,比如原先我們的HomeController,默認情況下我們可以通過’/’訪問也可以通過’/Home/’ 訪問,這其實有歧義的,為了避免這種情況,我們必須去修改Route,非常不方便,而現在,我們只需要在Pages主目錄下創建相應的Action就可以了,微軟提供了Razor Page的對應Url關系,如圖:

image

快速自定義Routing

你是否會問現在還支持/Controller/Action/ID 嗎?

支持,不過你需要在cshtml頁面上,通過@page設置路由

@page "{parameter:type?}"

例如 /Address/Province/City  我們只需要在Address/Index.cshtml頁面上加入如下:

@page "{Province}/{City?}"

問號代表可選參數。這樣的好處就是我們不需要在RegisterRoute的時候去填寫規則了,是不是很棒!Flirt male

那像原來我們在一個Controller中,有Get()和Get(id)表示獲取列表和獲取單個Item,那在Razor Page中如何運用呢?

抱歉,目前我沒有找到最佳的解決方法,原本我打算在@page "~/user/{id:int}",但是測試結果發現不支持,因為我們的page對應到url也是一個目錄,@page route的時候它不會識別絕對路徑和相對路徑,它只會在當前路徑后面添加映射,也就是說我們的url變成了/users/user/{id},目前最佳的解決方式是建立兩個目錄,如下:

image

 

模型綁定

在Razor Page中,數據綁定是非常簡單的, 您只要在需要綁定的屬性上添加[BindProperty]特性即可。

public class IndexModel : PageModel
{
    
    public string Message { get; set; }

    [BindProperty]
    public User TestUser { get; set; }

}

public class User
{
    public Guid UserID { get; set; }

    public  string Name { get; set; }
}

默認情況模型綁定不支持Get方法,你需要使用[BindProperty(SupportsGet=true)]

TempData 臨時數據

TempData是Asp.Net Core 2.0新增的特性,你只需要在PageModel中的屬性上加上TempData特性即可。加上TempData特性的屬性,會在你跳轉路由或者頁面的時候隱性的傳遞過去。

什么意思呢?比如當你創建一個用戶的時候,你會希望跳轉回用戶列表頁,並在用戶列表頁提示添加成功的信息,這時候你可以通過在Message屬性上加上[TempData]特性,引用下微軟Docs的例子:

public class CreateDotModel : PageModel
{

    [TempData]
    public string Message { get; set; }


    [BindProperty]
    public Customer Customer { get; set; }

    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }
        //todo create a new customer
        Message = $"Customer {Customer.Name} added";
        return RedirectToPage("./Index");
    }
}

跳轉到Index后,我們的IndexModel的Message屬性(需要同樣設置TempData特性)就會被賦值。有點類似於之前的model傳遞,但又不一樣,感覺棒棒噠!

遇到的一些問題

Q:自定義routing的時候,無法支持絕對路徑和相對路徑

A:應該可以通過重寫某個接口達到目的,稍后我會看下

Q:不支持多個handler在同一個pageModel中,比如OnGet, OnGetAsync不能在同一個PageModel中

A:可以通過自己重寫IPageHandlerMethodSelector接口,然后注冊到service中應該可以解決。

Q:用VS2017創建新的Page的時候,會在頁面上顯示紅線

A:關閉頁面再打開。。。。

寫在最后

    最近工作有點忙,Core2.0的出現使Net圈沸騰了,RazorPage的出現更是讓我們這種web開發者為之振奮,今天介紹的有限,畢竟也是剛出來的東西。個人覺得Razor Page還是非常棒的,雖然還有些問題,如果遇到Razor Page無法解決的事情,請大家結合MVC,國外有大神就是這么做的,但我相信不久之后,Razor Page會瘋狂出現在我們面前,特別是對於微服務架構來說,簡單和快速是微服務的重要所在。

    最后推薦下自己的.Net Core學習群:376248054


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM