7 天玩轉 ASP.NET MVC - 第 1 天

0. 前言

正如標題「7 天玩兒轉 ASP.NET MVC」所言,這是個系列文章,因此將會向你們陸續推出 7 篇。設想一下,一天一篇,你將從一個愉快的週一開始閱讀,而後在週末成爲一個 ASP.NET MVC 開發者,這很酷吧!html

7 天玩兒 轉 ASP.NET MVC — 第 1 天

第一天是熱身運動,這篇咱們將圍繞 Controller 和 Views 實踐兩個 Labs。在每一個 Lab 之中都伴隨着一些 Question 和 Answer。因此文章的主體框架是 Lab 和 Q&A。web

7 天玩兒 轉 ASP.NET MVC — 第 1 天

1. 開始以前的準備

咱們只須要 Visual Studio 工具就能夠開始 ASP.NET MVC 之旅。你能夠經過 Visual Studio 官網 下載所需版本。編程

2. MVC vs Webforms

許多 ASP.NET 開發者第一次接觸 MVC 時會認爲它是區別於 Webforms 的,會認爲它是一個全新的技術。確實如此,若是說 ASP.NET Webforms 是一個建立 Web Application 的框架,那麼 ASP.NET MVC 就是一個更棒的架構體系,它以一種更合理的方式來組織和放置咱們的代碼。瀏覽器

不能否認的是,ASP.NET Webforms 在過去十多年都很是流行,從 VB 開始,微軟就開始傳經佈道 RAD 和 Visual Programming 的方法。連微軟的開發工具都稱做 Visual Studio,可見一斑。服務器

經過使用 Visual Studio,開發者能經過拖拽的方式將 UI 構件放置到設計界面,Visual Studio 便自動爲這些構件產生 C# 或者 VB.NET 代碼。這些可被稱做爲「Code Behind」 ,在「Code Behind」區域內,開發者能夠來寫一些邏輯代碼。架構

7 天玩兒 轉 ASP.NET MVC — 第 1 天

因此微軟的 Visual RAD 方法實際上就是兩件事,UI 和 Code Behind。例如 ASP.NET Webforms,有 ASPX 和 ASPX.CS;對於 WPF,有 XAML 和 XAML.CS,不一而足。mvc

3. ASP.NET Web Forms 的問題

既然 ASP.NET Webform 如此成功,爲何微軟還要考慮建立 ASP.NET MVC 呢?主要緣由是出在 ASP.NET Webform 的性能上。能夠從兩個性能角度考慮:框架

  1. 響應時間:Server 端響應請求的時間是多少?
  2. 帶寬消耗:多少數據被傳輸?

咱們來嘗試解釋爲何 ASP.NET Webforms 的響應時間很慢。經過一個小的負載測試,咱們發現 ASP.NET MVC 比 ASP.NET Webforms 快2倍左右。asp.net

7 天玩兒 轉 ASP.NET MVC — 第 1 天

假如 ASPX 有這樣一段關於 Text Box 的簡單代碼。ide

<asp:TextBox ID="TextBox1" runat="server">

而後爲 Text Box 寫一些後臺邏輯代碼,爲它進行賦值和背景色的操做。

protected void Page_Load(object sender, EventArgs e)
{
     TextBox1.Text = "Make it simple";
     TextBox1.BackColor = Color.Aqua;
}

運行程序後,將會在 HTML 頁面看到輸出。

7 天玩兒 轉 ASP.NET MVC — 第 1 天

若是你查看 HTML 的源代碼,它是這樣的:

<input name="TextBox1" type="text" value="Make it simple" id="TextBox1" style="background-color:Aqua;" />

如今中止閱讀,閉上眼睛思考片刻:

  1. 這真的是一個建立 HTML 的高效方式嗎?咱們真的須要開始這樣一個漫長的服務器響應之旅而只是爲了在瀏覽器上顯示如此簡單的頁面嗎?
  2. 難道開發者們不能直接寫 HTML 頁面嗎,難道很難寫?

7 天玩兒 轉 ASP.NET MVC — 第 1 天

事實上,每一次請求都會有一次 Conversion 邏輯在運行,它用於轉換 HTML 輸出的控件。當咱們輸出的控件是一些 Grids 表格, Tree View 樹形控件等一些複雜的 HTML 頁面時,這種轉換將會變得更耗時,而且很是複雜,使得等待時間更長。

爲了解決這個問題,開始拋棄「Code Behind」吧,寫一些純淨的 HTML。

長期從事 ASP.NET 的開發者必定很是熟悉 Viewstate,它可以自動保存 post 返回的狀態而且減小了開發時間。可是正是因爲這種開發時間的減小帶來了巨大的代價,Viewstate 增長了頁面的大小。經過負載測試,對比 ASP.NET MVC,咱們發現 Viewstate 增長了近兩倍的頁面大小。

7 天玩兒 轉 ASP.NET MVC — 第 1 天

大小的增長是因爲 Viewstate 產生了額外的字節。下圖是 Viewstate 的截圖快照。也許有人會反駁放棄 Viewstate 的觀點,可是對於開發者而言,若是有其它選擇,他們會嘗試其它選擇。

7 天玩兒 轉 ASP.NET MVC — 第 1 天

爲了解決這個問題,開始拋棄 Server 控件吧。

自定義 HTML

由於咱們都是經過 ASP.NET 控件和後臺代碼來編寫應用,因此咱們沒有辦法來決定什麼樣的 HTML 被輸出,也不知道它們的效率是如何的。例如咱們能夠看一段 ASPX 代碼,你能夠試猜測一下什麼樣的 HTML 將被產生。

<asp:Label ID="Label1" runat="server" Text="I am label">
<asp:Literal ID="Literal1" runat="server" Text="I am a literal">
<asp:Panel ID="Panel1" runat="server" Text="I am a panel">

Label 控件會生成 DIV 仍是 SPAN 標籤?若是你運行一下代碼會發現,Label 控件被轉換爲一個 SPAN,Literal 控件被轉換爲一個簡單的 Text,而 Panel 控件則被轉換爲一個 DIV。

<span id="Label1">I am label</span>
I am literal
<div id="Panel1">I am panel</div>

所以與其使用 Server 控件來生成 HTML,倒不如直接手寫一些 HTML 來實現一些 HTML 控件。

因此,解決方案即是,不要再使用 Server 控件,直接編寫一些 HTML。
直接編寫 HTML 也帶來一些好處,這使得 Web 設計者可以和開發團隊緊密工做。Web 設計者可使用 DreamWeaver 或者 FrontPage 來獨立設計並獲取 HTML 代碼。若是咱們使用了服務器控件,這些設計工具便不能很好地識別。

後臺代碼可重用性

若是你看到過專業的 ASP.NET Webform 項目,你會發現它的後臺代碼常常會囊括很大的代碼量,而且代碼真的很複雜。這些代碼繼承「System.Web.UI.Page」類,而這個類也不是一個常規的類,它不能夠被重用或者實例化。換言之,你永遠沒法在一個 Webform 類裏作這樣的事情:

WebForm1 obj = new WebForm1();
obj.Button1_Click();

由於「WebForm」類沒有「Request」和「Respnse」對象是不可以被實例化的。能夠從下面的代碼中看到「WebForm」的「ButtonClick」事件代碼,從這段代碼中你就能夠看到爲何實例化會很難實現。

protected void Button1_Click(object sender, EventArgs e)
{
    // The logic which you want to reuse and invoke
}

單元測試

基於以前所說的後臺代碼沒法直接實例化,因此可想而知的是,單元測試或自動化測試都是很是困難的。開發者只能自動運行應用進行手動測試。

4. 解決方案

經過以前的分析,咱們發現 ASP.NET Webforms 的兩個關鍵因素:「Code Behind」和「Server Controls」,即後臺代碼和服務器控件。它們影響的代價和解決方案以下圖所示:

7 天玩轉 ASP.NET MVC — 第 1 天

咱們須要的解決方案即是將後臺代碼遷移到獨立的簡易類庫,而且放棄 ASP.NET Server 控件,寫一些簡單的 HTML 頁面。
簡而言之,解決方案就像以下圖的形象說明,將 Web Form「減肥」爲 MVC。

7 天玩轉 ASP.NET MVC — 第 1 天

5. ASP.NET MVC 如何解決 Webforms 的問題

正如咱們以前所討論的,後臺任務和服務器控件是問題的根源。因此若是你看一下當前的 Webform 架構體系就會發現,開發者使用的幾乎就是 3 層架構體系。

這 3 層架構體系包含了 UI,這個 UI 實際上包含了 ASPX 和 後臺代碼。

7 天玩兒 轉 ASP.NET MVC — 第 1 天

ASP.NET MVC 包含了三部分,即 Model,View 和 Controller。Controller 負責後臺邏輯代碼。View 是純淨的 HTML 頁面。Model 是中間數據層。

這裏有兩個主要的改變,其一是 View 變爲簡單的 HTML 頁面,其二是後臺代碼轉換爲簡單的 .NET 類,咱們稱之爲 Controller。

ASP.NET MVC 的請求流以下:

  • 第一步:首先觸發 Controller。

  • 第二步:依據行爲 Controller 建立 Model 對象。Model 反過來經過調用數據接口層來向 Model 對象填充數據。

  • 第三步:填充完的 Model 對象將數據傳輸給 View 層,而後展現出來。

7 天玩轉 ASP.NET MVC — 第 1 天

如今咱們已經理解 ASP.NET MVC 的各個組件了。接下來開始深刻學習每一個組件,而且作一些小的 Lab。咱們將從 Controller 開始,由於它是 MVC 架構體系的核心。

6. 如何理解ASP.NET MVC 中的 Controller

爲了理解Controller,咱們首先要理解「用戶交互邏輯」的概念。

什麼是交互邏輯?

場景 1

你是否仔細想過,當終端用戶在瀏覽器上敲下一個 URL 並按下回車後,會發生什麼事情?

7 天玩轉 ASP.NET MVC — 第 1 天

瀏覽器發送一個請求給服務器,服務器再作出響應。

7 天玩轉 ASP.NET MVC — 第 1 天

經過這種方式的請求,客戶端嘗試與服務器進行交互。服務器可以返回響應是由於服務器已經有了一些邏輯來處理這些請求。這個邏輯實際上承載了用戶的請求以及用戶與服務器的交互行爲,這即是用戶交互邏輯。

場景2

存在這樣一種可能,服務器返回的響應是一個 HTML 響應。這個 HTML 包含了一些輸入框或者提交按鈕組件。

7 天玩兒 轉 ASP.NET MVC — 第 1 天

當點擊「SaveCustomer」按鈕時,會發生什麼事情?

若是你的回答是「一些事件處理器來處理這個按鈕點擊」,那麼就錯了。

現實是 Web 編程是沒有事件的概念的。一種狀況是,微軟爲 ASP.NET Webforms 爲咱們寫了一些代碼,並給人一種事件驅動編程的感受。實際上,這只是一個錯覺或者幻想。

當按鈕被點擊後,一個簡單的 HTTP 請求就被髮送到服務器上。此次不一樣的是,「Customer Name」,「Address」和「Age」的值都將伴隨着請求被髮送。從根本上說,若是發生了請求,那麼服務器就會根據已經寫好的邏輯發出返回響應,簡而言之,服務器上必定存在一些用戶交互邏輯。

在 ASP.NET MVC 中,最後一個字母「C」就表明的是 Controller,它是用於處理用戶交互邏輯的。

7. Lab1 - 從簡單的 MVC Hello World 來理解 Controller

建立 ASP.NET MVC 5 程序

打開 Visual Studio 2013 或更高版本,點擊 文件 > 新建 > 項目。

7 天玩轉 ASP.NET MVC — 第 1 天

選擇 Web 應用,填寫應用名稱,選擇應用路徑,點擊肯定。

7 天玩轉 ASP.NET MVC — 第 1 天

選擇 MVC 模板文件

7 天玩轉 ASP.NET MVC — 第 1 天

點擊更改權限,在對話框中選擇「無權限」。

7 天玩轉 ASP.NET MVC — 第 1 天

點擊肯定便可。

建立 Controller

在資源管理器中,右擊「Controller」文件夾,點擊 添加 > 控制器。

7 天玩兒 轉 ASP.NET MVC — 第 1 天

選擇 MVC 5 控制器,點擊添加。

7 天玩轉 ASP.NET MVC — 第 1 天

將控制器命名爲「TestController」,而後點擊添加。

有一點很是重要,不要刪除「Controller」這個單詞,它是控制器的關鍵字。

7 天玩轉 ASP.NET MVC — 第 1 天

建立行爲方法

打開剛剛建立的「TestController」類,你會發現裏面有一個方法叫「Index」,將這個方法刪除,而後建立一個新的公開方法,稱爲「GetString」。

public class TestController : Controller
{
    public string GetString()
    {
        return "Hello World is old now. It's time for wassup bro ;)";
    }
}

執行並測試

按下 F5。在地址欄中以「ControllerName/ActionName」的格式輸入。可是須要注意的是,不要將控制器的名稱「Controller」加上,直接寫「Test」便可。

7 天玩轉 ASP.NET MVC — 第 1 天

8. 圍繞 Lab 1 的 Q&A

TestController 和 Test 的關係?

「TestController」是一個類的名稱,然而「Test」確是一個控制器的名稱。須要注意的是,當你在 URL 中輸入控制器的名稱時,不要帶上單詞「Controller」。

什麼是 Action「行爲」方法?

Action 方法是一個在控制器裏的簡單公共方法,它負責接收用戶的請求,並返回一些迴應。經過上述的例子,能夠看到行爲方法「GetString」是返回一個字符串迴應。

注意:在 ASP.NET Webforms 裏,默認返回的都是 HTML。有一種情形是,若是咱們想返回一些其它非 HTML 類型的請求,就得要建立 HTTP 處理器,重寫內容類型,而後作出迴應。這並非一個簡單的任務。可是在 ASP.NET MVC 中是很容易的。你像返回「String」就返回一個「String」,而不須要返回一個完整的 HTML 頁面。

若是在一個 Action 方法中,返回是一個對象,會發生什麼?

查看如下代碼。

namespace WebApplication1.Controllers
{
    public class Customer
    {
        public string CustomerName { get; set; }
        public string Address { get; set; }
    }
    public class TestController : Controller
    {
        public Customer GetCustomer()
        {
            Customer c = new Customer();
            c.CustomerName = "Customer 1";
            c.Address = "Address1";
            return c;
        }
    }
}

輸出 Action 方法以下。

7 天玩轉 ASP.NET MVC — 第 1 天

當返回的類型是「Customer」這樣的對象時,它會返回對象的實現方法 「ToString()」。方法「ToString()」 默認返回類的全名,即 「NameSpace.ClassName」這樣的形式。

若是想獲得上述例子的屬性值該如何操做?

直接重寫類的方法「ToString」便可。

public override string ToString()
{
    return this.CustomerName+"|"+this.Address;
}

按下 F5,查看輸出結果。

7 天玩轉 ASP.NET MVC — 第 1 天

Action 方法前必定要加上 public 修飾符嗎?

答案是確定的,Action 方法都自動加上 Public 修飾符。

非 Public 方法如何理解?

這些非 Public 方法只是類內部的非公開方法,簡單理解就是它們不能被 Web 調用。

若是咱們想實現一個 Public 的非 Action 方法,該如何去作?

只是簡單地加上 NonAction 屬性便可。

[NonAction]
public string SimpleMethod()
{
    return "Hi, I am not action method";
}

當咱們試着調用以下 Action 方法,會獲得以下的響應。

7 天玩轉 ASP.NET MVC — 第 1 天

9. 理解 ASP.NET MVC 中的 Views

就像咱們剛纔理解的 Controller 是用於處理用戶的請求並返回響應。大多數狀況下響應的是一個 HTML 頁面,瀏覽器可以很好地理解這種格式。 HTML 有一些圖片,文本,輸入控件等。通常來講,在技術領域定義用戶接口設計的層稱爲 UI 層,在 ASP.NET MVC 中稱爲 View。

10. Lab2 - 演示 Views

在 Lab1 中咱們建立了一個簡單的 MVC 應用,只有一些 Controller 和一些簡單的返回值。如今咱們爲 MVC 添加 View 的部分吧。

建立一個 Action 方法

在 TestController 中增長一個 Action 方法。

public ActionResult GetView()
{
    return View("MyView");
}

建立一個 View

右擊剛纔的 Action 方法,選擇「Add View」。

7 天玩轉 ASP.NET MVC — 第 1 天

在「Add View」對話框中添加一個視圖,命名爲「MyView」,取消「Use a layout」複選框,並點擊「Add」。

7 天玩轉 ASP.NET MVC — 第 1 天

在解決方案瀏覽器下,就會發現「Views/Test」文件夾增長了一個新的視圖。

7 天玩轉 ASP.NET MVC — 第 1 天

打開「MyView.cshtml」文件,將會看到內容以下。

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
  <head>
     <meta name="viewport" content="width=device-width" />
     <title>MyView</title>
  </head>
<body>
    Welcome to MVC 5 Step by Step learning
<body>
</html>

測試並運行

按下 F5,執行應用程序

7 天玩轉 ASP.NET MVC

11. 圍繞 Lab 2 的 Q&A

爲何視圖被放到了 Test 文件夾下?

在 ASP.NET MVC 中,Views 老是與特定的 Controller 相關聯被放到一個特殊的文件夾中。這個特殊的文件夾將以 Controller 的名字命名而且放到 Views 文件夾中(它位於根文件夾)。對於每個 Controller 要訪問的視圖而言,只有放在正確的文件夾中才是可用的。

例如:關聯 TestController 的全部視圖都將被放置在「~/Views/Test」下,而且 TestController 只能訪問 Test 文件夾下的視圖。

對於多個控制器而言,能夠重用一些視圖嗎?

答案是確定的。咱們將這些視圖文件放到一個指定的文件夾下,即「Shared」。

7 天玩兒 轉 ASP.NET MVC — 第 1 天

在「Shared」文件夾下的視圖文件可以被全部控制器共享。

一個 Action 方法能夠引用多個 Views 嗎?

答案是確定的。以下代碼:

public ActionResult GetView()
{
    if(Some_Condition_Is_Matching)
    { 
       return View("MyView");
    }
    else
    {
       return View("YourView");
    }
}

View 功能的目的是什麼?

建立 ViewResult 對象,用於視圖作出迴應。

  1. ViewResult 內部建立 ViewPageActivator 對象
  2. ViewResult 選擇正確的 ViewEngine,並將 ViewPageActivator 對象做爲參數傳輸給 ViewEngine 構造函數。
  3. ViewEngine 建立 View 類的對象。
  4. ViewResult 調用 View 類的 RenderView 方法。

ActionResult 和 ViewResult 之間的關聯?

ActionResult 是一個抽象類,而 ViewResult 是 ActionResult 的多層子類。多層是由於 ViewResult 是 ViewResultBase 的子類,而 ViewResultBase 是 ActionResult 的子類。

若是咱們想要返回 ViewResult,爲何定義的返回類型是 ActionResult?

這是爲了實現多態,看以下例子:

public ActionResult GetView()
{
    if(Some_Condition_Is_Matching)
    { 
        return View("MyView");
    }
    else
    {
        return Content("Hi Welcome");
    }
}

在上面的例子中,一些場景下,咱們調用「View」函數將返回 ViewResult 類型,而一些其它場景下,咱們調用「Content」函數用於放回內容結果。

什麼是 ContentResult?

ViewResult 呈現了一個完整的 HTML 響應而 ContentResult 呈現的時一個純文本響應。就像返回一個純 String 類型意義。所不一樣的是,ContentResult 是一個 ActionResult 類型 ,包裝String 結果。ContentResult 也是 ActionResult 的子類。

能夠無參調用 View 函數嗎?

答案是能夠的。View 函數會經過當前的「ActionName」來找視圖。

第 2 天咱們將會學到什麼?

第 2 天中,咱們將討論 Models,Validation,Jquery 以及 Json。因此,讓咱們一塊兒搖擺,一塊兒學習吧!

原文地址:Learn MVC Project in 7 days

本文系 OneAPM 工程師編譯整理。想閱讀更多技術文章,請訪問 OneAPM 官方博客

相關文章
相關標籤/搜索