DotNetCurry 網站看到精彩的系列文章,細數了 ASP.NET 的一路發展。讀著讀著,勾起一堆塵封多年的回憶,滿是感動...

ASP.NET 發展至今已 17 個年頭,老人家出道早,有幸全程參與,平日靠它搞定工作大小需求,說起來也算我的衣食父母 😛 看在這點份上,我摘要了系列文的重點,補上個人詮釋並彙整一些過去發表過的相關文章,為自己這十多年的青春歲月留下見證。

註:標題如果讓你聯想到「時間簡史」、「人類簡史」等神作,在此致歉,本文只是「簡單描述 ASP.NET 的歷史」,真心不騙。藺相如,司馬相如,名相如,實不相如...

ASP.NET Web Form 誕生 (2002 - 2003)

ASP.NET 最早隨 .NET Framework 1.0 於 2002 年發佈,那是 XML 稱霸天下的年代,.COM 泡沫化的前夕,所有人忙著將桌面程式轉成網站,夢想著什麼鬼東西加個"e"就能發大財。(有個笑話是乞丐也得轉型成 e-Begger)

2000 年代的微軟遇到幾項挑戰:

  • 發展 Java 開發工具(Visual J++、Visual J#)的構想引來版權訴訟,微軟需要自己的程式語言跟 Java 分庭抗禮
  • 急需一個基於 Windows 的網站平台以免在 .COM 盛世缺席
  • RAD(Rapid Application Development),讓開發者拖拉點選寫寫 Code 就能生出程式的 VB6 需要接班人

為滿足這些需求,微軟推出 Visual Studio.NET,開發語言進入 .NET 時代,ASP 開發者有 C# 與 VB.NET 可選(我選了 C#)。WebForm 沿襲 VB6 的視覺化設計開發風格,在 IDE 裡拖拉 Label、TextBox、Button 調整位置跟大小,點兩下切換到程式碼區寫點擊後要執行的動作。

由於具有與 WinForm 高度相似的友善開發環境,神奇地讓許多 WinForm 開發者無痛進化成能用 WebForm 打造各式網站的即戰力。

WebForm 分成兩個檔案 WebForm.aspx 跟 WebForm.aspx.cs,前者以 HTML 標籤為主,可沿用 ASP 或 PHP 概念以 <% = serverSideVariable %> 在網頁插入伺服器端決定的動態內容,但主流寫法是以 <asp:TextBox> <asp:Button> 形式在 HTML 間穿插各種好用 Server Control。.aspx.cs 則是伺服器端程式邏輯,以 C# 或 VB.NET 開發。

Server Control 可以用 Visual Studio 視覺化移動位置調整大小,點兩下則帶到 .aspx.cs 中的事件方法。執行時,當使用者做了某些動作需要執行後端 C# 程式,WebForm 機制會記下網頁當時狀態(ViewState),觸發送出網頁動作,後端處理後重新產生頁面,並依據 ViewState 保存內容還原網頁送出前狀態。例如:使用者在 TextBox 中輸入 Jeffrey,按下 Button,瀏覽器送出表單,伺服器端處理後重新顯示網頁,使用者看到某個 Label 內容變成"Hello, Jeffrey",但要將 TextBox 還原按鈕前所輸入的 Jeffrey,使用者完全察覺不到背後歷經了一次瀏覽器與伺服器間來回傳送... 才怪! 這種 PostBack 觸發伺服器端事件做法瀏覽器需要消除網頁重新產生,畫面會明顯閃一下再更新,使用者不發現才有鬼。(於是 AJAX 時代出現了 UpdatePanel 試圖解決這個問題)

WebForm 其實有機會依循設計模式寫到很結構化,例如採用 MVC、Front Controller、Intercepting Filter... 等等,但大部分開發者多半深陷 RAD 的便利無法自拔,沈醉於拖拉控件寫寫事件就做出網站的成就感。光明面是讓許多不懂 HTML、HTTP、JavaScript 的開發者得以進入網站開發殿堂,黑暗面則是催生許多存在安全漏洞及難以維護的可怕網站。這是所有低門檻便利科技的一體兩面,臉書、PTT 人人會用,讓我們看到很多原本要被埋沒的絕世好文,伴隨數不盡的廢文酸文及網路霸淩。

ASP.NET 2.0 (2003 - 2008)

2003 推出的 Visual Studio.NET 2003 與 .NET 1.1,只加入行動裝置控件跟小幅調整。2005 推出 Visual Studio 2005 與 .NET 2.0,.NET 2.0 加入泛型、Nullable<T>、Partial Class、TransactionScope 等革命性改良,ASP.NET 也大幅進化,開始支援 MasterPage、Site Map、跨網頁 PostBack、Web Part、Membership/Profile Provider,變得更方便好用。

ASP.NET 2.0 的另一項創新是 Web Site Project,帶來不需編譯部署即可更新網站的便利性。這部分可參考舊文:Web Site Project vs Web Application Project閒聊:Web Site Project為何沒落?

2005 年代 AJAX 網頁開始盛行,就算執行伺服器端動作網頁也能流暢更新的 AJAX 體驗屌打按個鈕移個欄位切個下拉選單就會閃一下的 PostBack 式更新,但同年推出 ASP.NET 2.0 來不及跟上潮流,2007 年先以 Microsoft AJAX 1.0 套件方式發行,為 ASP.NET 2.0 加上 AJAX 更新功能,新增可整合 JavaScript 的日期選擇器、可連動下拉選單... 等控制項、神奇的 UpdatePanel、古早版 JavaScript 型別系統(當然不能與 TypeScript 相提並論,但當時已是創新)、ASMX 與 WCF 的 JavaScript Proxy... 等等。

Microsoft AJAX 裡的 UpdatePanel 最值得一提,它再一次神奇地讓不懂 JavaScript 的開發者也能寫出 A"J"AX 網頁,但魔法背後常需付出代價(放心,不到用聲音去換雙腳這麼嚴重),UpdatePanel 很容易搞出超肥大的笨重網頁,細節可參考舊文:UpdatePanel招誰惹誰?

在 Microsoft AJAX 發佈之前,2006 年底還有另一件事 - .NET 3.0 與 WCF、WPF、WF(Windows Workflow Foundation) 也誕生了,但一年多後更震憾的革命正要登場!

ASP.NET .NET 3.5 與 MVC 初試啼聲 (2008 - 2011)

Visual Stduio 2008 於 2008 年初上市,為大家帶來了 .NET 3.5 LINQ,戲劇性地簡化 .NET 程式碼行數及繁瑣度,讓許多 .NET 開發者嚴重成癮,無可救藥到(LINQ or Die)「無 LINQ,吾寧死」的地步,不過 LINQ 屬 .NET 層次的體革新非 ASP.NET 專屬,在此不多談。還對 LINQ 無感的同學可以參考這篇推坑文:好 LINQ,不用嗎?,看有沒有機會來電促成良緣。另外,ASP.NET 3.5 的一項革新是將 Microsoft AJAX 整為內建,不需額外安裝。但 ASP.NET 真正的革命已不在 WebForm,而是另開路線展開。

隨著時代演進,網頁設計主流愈來愈向 JavaScript 傾斜,以 HTML 及 JavaScript 為運作核心,棄用 PostBack 完全以 ASMX、WCF、WebAPI 整合伺服器端作業的 SPA (Single Page Application) 概念興起,肥大笨重的 XML 也慢慢被容易用 JavaScript 操作且輕巧的 JSON 取代。傳統 WebForm 與 Microsoft AJAX 隱藏了 JavaScript 實作細節,要融合 SPA、JSON 困難重重。

有鑑於此,微軟從 2007 開始研發名為 ASP.NET MVC 的新架構,採取與 WebForm 大異其趣的設計思維,包含:

  • 貫徹「觀注點分離」(Separation of Concept)設計原則
  • HTML 產生交由開發者完全掌控
  • 優先支援 TDD (Test Driven Development)
  • 整合 Caching、Session、Module、Handler、IIS Hosting 等現有 ASP.NET 機制
  • 可抽換式模組設計,Controller、View Engine 可替換改用客製版本
  • 使用 ASPX View Engine (但不包含 ViewState 及 PostBack),但也可抽換成 MonoRail 等第三方引擎
  • Controller 支援 IoC (Inversion of Control) 及 DI (Dependency Injection)
  • 完整的自訂 URL 路由支援

早在 2003 年代微軟就在 Microsoft's Patterns and Practices 倡議網站應實踐 MVC、Front Controller 等設計模式,.NET 社群也做過類似乎努力,例如受 Ruby on Rail 啟發所發展的 MonoRail,而 ASP.NET MVC 是微軟自己依循 MVC 原則的實作,並開啟先河以 Open Source 方式發展,於 2009 年釋出 1.0 版。

關於 MVC 的基本觀念,過去寫過的豬走路系列有較完整介紹,在此不多贅述:

ASP.NET MVC 的出現對 WebForm 的長期發展策略帶來衝擊,開發社群反應分歧。WebForm 支持者認為 WebForm 成熟穩定,開發快速有效率;MVC 則學習曲線陡峭,需較長學習時間才能上手,現有人員已具備 WebForm 開發技能,對追求快速開發的單純企業應用,WebForm 才是王道。更別提由 WebForm 轉向 ASP.NET MVC 需放棄既有系統框架、Server Control 程式庫,並有重新學習技能的人力成本。MVC 支持者則主張,ASP.NET MVC 基本上是順應網頁開發潮流而生,力求符合主流設計概念(觀注點分離、IoC/DI、TDD、SPA...),強迫將前後端邏輯切乾淨是好事,模組可抽換式的彈性設計更容易調校應付高負載情境,大幅超越 WebForm 的效能極限。即使你不喜歡,天要下雨,娘要嫁人,整個網站設計主流就是這麼走,不跟上去難道要故步自封,忍受自己與時代愈來愈脫節? (我屬於後者:丞相,起風了!從ASP.NET 5的變革談起,WebForm 絕對可以再戰十年,但小心別成為困在浮冰上的北極熊)

在 JavaScript 架構方面,蒐集各式 jQuery 插件打造前端網頁的做法漸漸被以 MVVM/MVC 為核心的前端框架取代,2010 年一度是 Backbone、Knockout、AngularJS 三足鼎立(九年後已人事全非)。完全掌控 HTML、CSS、JavaScript 再以 AJAX 整合伺服器端邏輯成為王道,從這個角度,ASP.NET MVC 遠遠勝過 WebForm。自此風向漸轉,

ASP.NET MVC 成熟 (2011 - 2013) - MVC 3/4, Web API, SignalR

2011 年推出的 ASP.NET MVC 3.0 是個重要里程碑,Razor 革命性地簡化 View 寫法,而仿效 RubyGems 與 NPM 的 NuGet 套件機制讓程式庫的搜尋、下載、安裝、更新、發行變得無比簡單。自此,ASP.NET MVC 算是成熟到可被企業接受,開始用在一些觀念驗證(PoC)、先導性質的低風險小專案,並累積成功經驗後逐步推度到在中大型專案。而 TDD、SOLID 原則、DI、單元測試也漸漸成為 .NET 開發者朗朗上口的詞彙。

於此同時,微軟還推出了 Web Pages(WebForm + Razor)、WebMatrix(IIS Express 整合網頁開發 IDE)等新技術,但偏向小眾市場。

2012 年 ASP.NET MVC 4 誕生,因應智慧型手機盛行,加入基於 jQuery Mobile 的行動模板(偵測 UserAgent 自動切換桌面及手機平板瀏覽模式,未整合成單一版型是當時 RWD 還沒當道),而此時真正的明星是 REST Web API,ASP.NET MVC 加入 ApiController,簡化 RESTful Web API 實做細節,隨後 VS2012 更新再加入 SPA 專案範本,可整合 Knockout、AngularJS、Backbone 及 Web API。而 SingalR 也同年推出,讓 ASP.NET 開發者可以輕鬆寫出持續即時 AJAX 更新內容的網頁。

One ASP.NET (2013 - 2014) - MVC 5 & Web API 2

Visual Studio 2013 伴隨 .NET 4.5.1 一起於 2013 年晚期推出,將 ASP.NET WebForm、MVC、WebPages、Web API、SignalR 等產品整合在 One ASP.NET(我私自把它翻譯成「大 ASP.NET」)下,共用 ASP.NET 專案範本,再勾選要用 MVC、WebForm 或 Web API。Web API 進入 2.0 (就是前陣子文章常提的 Web API 2),強化了 OData、CORS 支援,加入 [Route("api/books")] 以 Attribute 自訂路由。而 ASP.NET MVC 也進化到 MVC 5,一樣支援 [Route()],強化 Scaffolding,加入 ASP.NET Indentity 程式庫用於身分識別與權限管控。另一項更新是網頁模版預載 Bootstrap 3,WebForm 雖然也加入新功能,但概念上是向 MVC 看齊,讓 WebForm 也能使用 Model Binder、Data Annotation、路由及 Unobtrusive JavaScript 等在 MVC 引進多時的功能。

2013 年起 React 開始在前端界攻城掠地(如今已是 SPA 界一方霸主),Node.js 與 NPM 經濟生態體系日益強大,最後主宰了當今前端開發的走向。

ASP.NET Core 現身 (2014 - 2017)

One ASP.NET 看似是 ASP.NET 長年發展集大成的最終產品,但微軟另有更遠大的計劃,一個代號為 ASP.NET vNext(後來更名為 ASP.NET 5,最終定名為 ASP.NET Core)的計劃正在同步進行。

ASP.NET 5 起源於 Katana 專案,受到 Ruby 跟 Node.js 的啟發,改用 OWIN 作為 ASP.NET 底層核心,擺脫對 System.Web 的依賴,讓 ASP.NET 可以在 IIS 以外的 Web Server 執行。最先做到 OWIN 相容的是 Web API 及 SignalR,最明顯特色是可以輕易改用 Console Appliation 跑 WebAPI 或 SignalR 服務,而 OWIN 精神現今已融合進 ASP.NET Core。

而 ASP.NET vNext 打從一開始的目標並不限於在 Windows 用 Console Appliction 跑 ASP.NET 這樣簡單,在 2014 年 David Fowler 關於 vNext 的文章就透漏將與 Mono 團隊合作將領土拓展到 *nix、OSX 的計劃。

Mono 是從 2004 年就開始的開源社群專案,目標是讓非 Windows 平台可以跑 .NET。(延伸閱讀:我不是在做夢吧? 令人感動的Mono!) 與 Mono 團隊合作的最大意義是微軟終於不再為保護自家作業系統的產品利益而限制 .NET/C# 發展,正式放手讓它不再被視為特定作業系統的附庸,而是跨越平台成為一種「堂堂正正的程式語言」。(每每提到這點就很有感慨,要是早幾年發生,以 C# 的出色特質,在程式語言界的地位絕對不只於此) .NET 開始建立可跨平台執行的 Runtime (當時叫 KRuntime)、重新設計 HTTP 抽象層及簡化 Hosting 等。

起初 vNext 推出 project.json 取代 .csproj,但在 Core 1.1.1 時棄坑回歸簡化版 .csproj 以維持與現有開發工具相容,這也象徵 .NET Core 團隊與 ASP.NET 與 Web Tools 團隊開始聯手推動下一代的 ASP.NET。一場 .NET 開源化革命正式展開,ASP.NET 被徹底重寫,與新一代 CLR 一起放上 Github 以 Apache 授權開源。

2014 年 ASP.NET 5 Preview 版明確勾勒出跨平台、不限網站伺服器、統一 MVC/Web API 模組、內建依賴注入、以 Middleware 概念重新打造 Request Pipeline,以及以 NuGet 程式包作為相依單位的目標。

全力聚焦於 GUI 開發工具多年,隨著前端界 Command Line Interface (CLI) 工具的盛行,KRuntime 也不再著重 GUI,改以 CLI 作為主要應用介面,包含 kvm (安裝及切換 Runtime 版本)、kpm (還原專案相依套件,編譯專案)、k (啟動應用程式)。沒多久,KRuntime 更名為 DNX Runtime,前述三個 CLI 也改名為 dnvm, dnu 與 dnx。到了 ASP.NET Core 1.0,再改為單一 CLI - dotnet,執行方式改為 dotnet list, dotnet restore, dotnet publish, dotnet run... 等。(最後定版名稱友善許多,但苦了從早期入場的白老鼠們)

2016 年五月,ASP.NET 5 正式更名為 ASP.NET Core 1.0,搭配 .NET Core Framework 運作,ASP.NET Core 1.0 與 ASP.NET 4.6 並存,功能完整度上 ASP.NET Core 1.0 仍落後 ASP.NET 4.5,需努力追趕。

2016 年六月 ASP.NET Core 1.0 正式推出,對 ASP.NET MVC 開發者,Controller 與 CSHTML Razor 寫法跟過去差異不大,要上手並不困難。而 Request Pipeline 改以 Middleware 方式串接組裝,遇到特殊需求,只需建立並註冊自訂 Middleware 即可抽換整個網站的身分認證方式。 但網站啟動與設定過程配合新 Hosting 的輕巧做法與 Middleware Pipeline 重新設計過,共用服務則一律改用依賴注入方式在建構方式取得,這部分與 ASP.NET MVC 4.5 差異較大,需要重新學習適應。

ASP.NET Core 1.0 CSHTML 方面新增 Tag Helper 及 View Component 取代 HtmlHelper 及 Partial View,使用上更方便。2016 年 11 月推出的 1.1.0 再做了小幅增強,像是 Middleware 可當成 Filter 使用,用 Tag Helper 產生任何 View Component。後者讓 View Component 能像 JavaScript SPA Framework Component 一樣方便使用,例如,用 @await Component.InvokeAsync("LatestArticles") 取代 <vc:latest-articles></vc:latest-articles> 的繁瑣寫法。.NET Core 1.1.0 之後還有 1.1.1 及 1.1.2 兩次小改版。

ASP.NET Core 2.0 (2017 至今)

ASP.NET Core 2.0 於 2017 八月釋出正式版,一大的變革是納入 Razor Pages,一個比較貼近 WebForm 精神的 MVVM 資料繫結、PostBack 運作架構,與 MVC 相較不倚重 HTML、JavaScript,大部分邏輯可用 C# 實現。(但千萬別幻想是在 ASP.NET Core 寫傳統 WebForm,Server Control Server-Side Event 那套機制確定不會再回來了) 如果你對 Razor Page 有興趣,可以參考官方文件:Introduction to Razor Pages in ASP.NET Core

ASP.NET Core 2.0 另一個新機制是 IHostingService,方便在網站應用程式很直覺且簡便的建立背景程序。

2.1.0 版在 2018 五月釋出,帶來針對 ASP.NET Core 重寫打造的 SignalR,以期充分運用 .NET Core 優勢。ASP.NET Core 至此也有 SignalR、Razor Pages (可視為 Web Form 與 Web Pages 精神重現),龍珠蒐集完成,「算是」涵蓋了整個 One ASP.NET 版圖。(說好不提 Web Form 跟 Server Control,大家把它忘了吧)

此外還有 Global Tools, 意指可安裝給全機使用的 .NET Core 額外 CLI 工具,Nate McMaster 有份清單蒐集了一些實用項目。(注意:Global Tools 受到系統完全的信任,安裝前請確認來源可靠)

展望即將問市的 .NET Core 3.0,會有幾項革新:

  • WinForms、WPF、UWP 將支援 .NET Core 3.0 (別太高興,只限 Windows 平台)
  • Blazor Framework 分為伺服器端及客戶端,伺服器端稱為 Razor Component,將隨 .NET Core 3.0 釋出(延伸閱讀:Razor Components預設啟用伺服器端預渲染,提升低速網路網頁瀏覽體驗);至於客戶端(在瀏覽器中執行 .NET,延伸閱讀:Blazor 預覽筆記)則維持實驗階段。
    Razor Components 的概念是由伺服器端渲染產生靜態 HTML,以 SingalR 即時更新前端顯示。 換句話說,雖然 WebForm 即將謝幕,上帝為堅持只學 C# 其餘免談的同學又開了一扇「不碰 JavaScript 也能寫 AJAX 網頁」的窗~ 延伸閱讀:Razor Components for a JavaScript-Free Frontend in 2019
    (註:.NET Core 3.0 Preview 4 時,Razor Components 再更名回 Server-Side Blazor)
  • Google gRPC 基於 HTTP/2 及 Protobuf,主打輕巧及高效能獲得不少觀注,將會正式整合到 ASP.NET Core 3.0。

最後,不能不提 .NET Core 在提升效能上的努力。2.2 加入 Span<T> 後,ASP.NET Core 榮登 TechEmpower 效能評測的第三名,開發團隊有信心下一版本將會更上層樓。

結語

放眼 17 年來 ASP.NET 的演變,歷經多次如同砍掉重練的技術革命,我們可以看到 ASP.NET WebForm 1.1 到 ASP.NET Core 3.0,所呈現的是截然不同的樣貌。但我發現很有趣的一點,「不會 JavaScript 但想寫網頁的 .NET 開發者」一直是 ASP.NET 開發團隊心中最柔軟的那一塊,從 WebForm Server Control、Web Pages 到 Razor Page,總有貼心解決方案,相較這些年在前端不時面對「想寫 OOO 就給我學好 XXX! 不然呷賽」的震憾教育,ASP.NET 世界真的好佛心好溫暖 XD

ASP.NET 的路線也很明確,如果想挑戰效能與架構最佳化的極限,MVC 會是你的首選;如果你不會 JavaScript 只想用 C# 打通關寫網頁,Web Pages / Razor Pages 能讓你如願;留在 ASP.NET 4.x 可善用既有程式庫與元件,改用 ASP.NET Core 則會帶你邁向跨平台的美麗新世界;不管你的需求是什麼,幾乎都能在 ASP.NET 找到方法實現。

回顧過往展望未來,願我寶刀不老,能跟著 ASP.NET 再戰十年~

The brief history of ASP.NET with my view points.


Comments

# by Soon

「在 Microsft AJAX 發佈之前,2016 年底還有另一件事...」 「Razore Components 的概念是由伺服器端...」 黑大您好,看到兩處小 typo~

# by Jeffrey

to Soon, 感謝,已修正。

# by ChrisTorng

該更新到最新 (4/18) .NET Core 3.0 Preview 4 資訊囉... https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-core-3-0-preview-4/ 第一條就說,Razor Components renamed back to server-side Blazor。 另應該加入 gRPC 資訊了,這是微軟要取代 WCF 的下一代通訊介面,不過可惜 (奇怪?) 的是只能綁在 ASP.NET Core 裡,不能在 .NET Core 跑 (若需要只能使用 Google 的 C++/C# 版本) (參考該網頁的第一個留言及回覆)。

# by Jeffrey

to ChrisTorng,感謝分享,已補充於本文。

# by ChrisTorng

才一天,又有大消息 https://devblogs.microsoft.com/dotnet/introducing-net-5/ 及小消息 https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-core-3-0-preview-5/

# by Slouchy

黑大 在 Microsoft AJAX 發佈之前,2016 年底還有另一件事 這邊應該是 2006 年?

# by Jeffrey

to Slouchy, Yes,typo 已更正,感謝~

# by Titangene

黑大,發現幾個 typo: Separaion of Concept Rubby on Rail Data Annontation

# by Jeffrey

to Titangene,感謝~~ (這 typo 率... 可以想見程式語言沒有Strong Type時,我會有多慘 Orz)

# by Eddy

CLI, Command Line Interface, 文中寫成Command Interface Line.

# by Jeffrey

to Eddy, 感謝指正。

# by shupen

看完只有一個感想,我老了...

# by Wei

Typo ?! 加入 [Rount("api/books")] 以 Attribute 自訂路由。

# by Jeffrey

to Wei, 沒錯,承襲本站優良傳統,野火燒不盡春風吹又生的錯字... orz 感謝指正。

# by SHIH Hung

Typo ?! 此外還有 Gobal Tools

# by Jeffrey

to SHIH Hung,不用懷疑,正是 Typo,感謝指正。(這篇的錯字率達到新的歷史高度惹... orz)

Post a comment