1. 程式人生 > >閱讀了這三篇文章,你也就基本理解了ASP.NET Core MVC框架的工作原理

閱讀了這三篇文章,你也就基本理解了ASP.NET Core MVC框架的工作原理

《200行程式碼,7個物件——讓你瞭解ASP.NET Core框架的本質》讓很多讀者對ASP.NET Core管道有深刻的理解,知道了ASP.NET Core框架針對每個請求的處理流程。在過去很長一段時間中,有很多人私信給我:能否按照相同的方式分析一下MVC框架。真實的MVC框架其實很複雜,所以我們依然按照類似的方式大刀闊斧地“砍掉”了很多“細枝末節”,利用一個Mini版本的模擬框架將真實ASP.NET Core MVC最核心的部分展示出來。和Mini版本的ASP.NET Core框架一樣,這個Mini版的ASP.NET Core MVC框架同樣採用真實框架一致的設計,並且是同樣可以直接執行的。為了更好的維護,我將這兩個模擬框架放到了github上。

ASP.NET Core Mini: https://github.com/jiangjinnan/AspNetCoreMini

ASP.NET Core MVC Mini:https://github.com/jiangjinnan/AspNetCoreMvcMini

[上篇]路由整合

整個MVC框架建立在路由中介軟體(《ASP.NET Core 3框架揭祕》下冊具有對路由中介軟體的專門介紹,本書正在參加京東滿100-50活動,錯過之前5折優惠的同學可以上車了)上。不論是面向Controller的Model-View-Controller程式設計模型,還是面向頁面的Razor Pages程式設計模型,每個請求指向的都一個某個Action,所以MVC框架只需要將每個Action封裝成一個路由終結點(RouteEndpoint),並通過自定義的EndpointDataSource註冊到路由中介軟體上即可。本篇著重關注MVC框架與路由中介軟體的整合,所以我們將Action方法的定義作了最大的簡化:Action方法都是無參方法,這樣我們就不需要考慮引數繫結的問題;Action方法的返回值都是Task或者Void,所有的請求處理任務都實現在方法中。閱讀全文…

public class FoobarController: Controller
{
    public void Foo();
    public Task BarAsync();
    public ValueTask BazAsync();
}

[中篇]請求響應

我們在《[上篇]:路由整合》將定義在Controller型別中的Action方法簡化成只返回Task或者Void的方法,並讓方法自身去完成包括對請求予以相應的所有請求處理任務,但真實的MVC框架對Action方法對返回型別沒有任何的限制。一般來說,我們傾向於將Action方法的返回型別定義成IActionResult、Task<IActionResult>或者ValueTask<IActionResult>。如果Action方法返回其他型別的物件,該物件最終還是會被轉換成IActionResult物件。在整個MVC框架針對請求的處理流程中,IActionResult物件主要負責針對請求的響應工作。本篇我們將對上面建立的模擬框架作進一步完善,接觸針對Action方法返回型別的限制。閱讀全文…

public class FoobarController: Controller
{
    public IActionResult Foo();
    public Task<IActionResult> BarAsync();   
    public ValueTask<IActionResult> BazAsync();
    public Foobar Qux();
    public Task<Foobar> QuuxAsync();
    public ValueTask<Foobar> CorgeAsync();
}

[下篇]引數繫結

模擬框架到目前為止都假定Action方法是沒有引數的,我們知道MVC框架對Action方法的引數並沒有作限制,它可以包含任意數量和型別的引數。一旦將“零引數”的假設去除,Action方法的執行就變得沒那麼簡單了,因為在執行目標方法之前需要繫結所有的引數。MVC框架採用一種叫做“模型繫結(Model Binding)”的機制來繫結目標Action方法的輸出引數,這可以算是MVC框架針對請求執行流程中最為複雜的一個環節。本篇文章對現有框架做進步完全,通過實現模型繫結接觸上面針對Action方法引數的限制。閱讀全文…

public class FoobarController: Controller
{
    public IActionResult Foo(Foo foo, Bar baz);
    public Task<IActionResult> BarAsync(Foo foo, Bar baz);   
    public ValueTask<IActionResult> BazAsync(Foo foo, Bar baz);
    public Foobar Qux(Foo foo, Bar baz);
    public Task<Foobar> QuuxAsync(Foo foo, Bar baz);
    public ValueTask<Foobar> CorgeAsync(Foo foo, Bar baz);
}