七天學會ASP.NET MVC (一)--深刻理解ASP.NET MVC

Day1

 

系列文章

七天學會ASP.NET MVC (一)——深刻理解ASP.NET MVChtml

七天學會ASP.NET MVC (二)——ASP.NET MVC 數據傳遞前端

七天學會ASP.NET MVC (三)——ASP.Net MVC 數據處理web

七天學會ASP.NET MVC (四)——用戶受權認證問題編程

七天學會ASP.NET MVC (五)——Layout頁面使用和用戶角色管理瀏覽器

 七天學會ASP.NET MVC (六)——線程問題、異常處理、自定義URL服務器

七天學會ASP.NET MVC(七)——建立單頁應用架構

 

ASP.NET vs MVC vs WebForms

許多ASP.NET開發人員開始接觸MVC認爲MVC與ASP.NET徹底沒有關係,是一個全新的Web開發,事實上ASP.NET是建立WEB應用的框架而MVC是可以用更好的方法來組織並管理代碼的一種更高級架構體系,因此能夠稱之爲ASP.NET MVC。mvc

咱們可將原來的ASP.NET稱爲 ASP.NET Webforms,新的MVC 稱爲ASP.NET MVC.框架

ASP.NET Web Form

ASP.NET 在過去的十二年裏,已經服務併成功實現Web 應用的開發。咱們首先了解一下爲何ASP.NET可以如此流行,併成功應用。編程語言

微軟編程語言從VB開始就可以成爲流行並普遍應用,都源於其提供的強大的Visual studio可以進行可視化的編程,實現快速開發。

使用VS時,開發人員可以經過拖拽UI元素,並在後臺自動生成這些界面的代碼。稱爲後臺代碼。在後臺代碼中開發人員能夠添加操做這些UI元素的邏輯代碼。

clip_image002

所以微軟的可視化RAD架構體系有兩方面組成,一方面是UI,一方面是後臺代碼。所以ASP.NET Web 窗體,包含ASPX和ASPX.CS,WPF包含XAML/XAML.CS等。

ASP.NET Web Form存在的問題

咱們不得不考慮的問題是,既然ASP.NET Web Form 如此成功且具備優點,爲何微軟還要推出ASP.NET MVC?主要是由於ASP.NET Webform的性能問題。在Web應用程序中從兩方面來定義性能:

1. 響應時間: 服務器響應請求的耗時

2. 帶寬消耗: 同時可傳輸多少數據。

響應時間

咱們能夠理解爲何ASP.NET Webform比較慢,如圖咱們作了一些小的加載測試。分別使用ASP.Net MVC和ASP.Net Webform,發現ASP.Net MVC的響應時間比Webform快了兩倍。

clip_image003

接下來咱們在思考一個問題爲何ASP.NET MVC的性能更好?看看下面這個示例,簡單的UI代碼和UI的後臺代碼。

假如一個textbox的ASPX頁面:

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

對應的UI後臺代碼:

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

運行結果:

clip_image004

若是查看HTML輸出,則會顯示以下代碼:

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

咱們再來思考上面提到的問題

1. 這種HTML生成方式是否頗有效?咱們是否爲了獲取如此簡單的HTML而長時間的消耗服務器

2. 開發人員是否能夠直接編寫HTML?很難實現嗎?

 

clip_image005

經過分析咱們能夠得知,每一次請求都有轉換邏輯,運行並轉換服務器控件爲HTML輸出。若是咱們的頁面使用表格,樹形控件等複雜控件,轉換就會變得很糟糕且很是複雜。HTML輸出也是很是複雜的。因爲這些沒必要要的轉換從而增長了響應時間。該問題的解決方案就是擺脫後臺代碼,寫成純HTML代碼。

帶寬消耗

ASP.NET開發人員都很是熟悉Viewstates,由於它可以自動保存post返回的狀態,減小開發時間。可是這種開發時間的減小會帶來巨大的消耗,Viewstate增長了頁面的大小。在作的加載測試中,與MVC 對比,咱們發現Viewstate增長了兩倍的頁面存儲。如下是測試結果:

 

clip_image006

頁面尺寸的增長是由於viewstate產生了額外的字節。下圖就是Viewstate的截圖。許多人可能會不一樣意此觀點,可是衆所周知,開發人員是如何工做的,若是有選擇,他們確定會採起別的選擇。

 

clip_image008

  1. HTML 消耗

如今由於咱們都是後臺代碼和ASP.NET web server控件的努力,咱們對於怎樣獲得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">I am a panel

     

     

Lable標籤會生成DIV標籤仍是SPAN標籤?運行後生成的HTML代碼的結果以下:label生成了span標籤,Literal生成了轉換爲了簡單的文本,而panel轉換爲了DIV標籤。

 <span id="Label1">I am label</span>I am a literal

  • I am a panel
  •  

所以與其生成HTML代碼,還不如直接編寫HTML代碼,並實現HTML控件。

因此該問題的解決方案是:不使用服務器控件,直接編寫HTML代碼。

直接編寫HTML代碼的好處在於web設計者能夠與開發人員緊密合做及時溝通。設計人員可使用他們喜好的設計工具來設計HTMl代碼,像dream weaver,前端頁面等,設計獨立。若是咱們使用服務器控件,這些設計者工具可能不會識別。

       2. 後臺代碼類的重用性

若是仔細觀察一些專業的ASP.NET Webform項目,你會發現後臺代碼類每每都包含了大量的代碼,而且這些代碼也是很是複雜的。而如今,後臺代碼類繼承了「System.Web.UI.Page」類。可是這些類並不像普通的類同樣可以處處複用和實例化。換句話來說,在Weform類中永遠都不可能執行如下代碼中的操做:

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

 

  •   3. 單元測試
    

既然沒法實例化後臺代碼類,單元測試也是很是困難的,也沒法執行自動化測試。必須手動測試。

  • 解決方案

既然講了ASP.Net Webform存在的兩大問題即服務器控件和後臺代碼,如下是根源圖,

clip_image009

那麼解決方案是什麼?

就是咱們須要將後臺代碼遷移到獨立的簡單的類庫,而且拜託ASP.Net服務器控件,並寫一些HTML示例。

ASP.NET Webform 和MVC 比較,以下圖:

clip_image010

Microsoft Asp.Net MVC 是如何彌補Web Form存在的問題的?

後臺代碼和服務器控件是一切問題的根源。因此若是你查看當前的WebForm體系結構,開發者正在使用的包含3層體系結構。三層體系結構是由UI包含ASPX及CS 後臺代碼。

UI,業務邏輯以及包含數據訪問的中間層

clip_image011

Asp.Net MVC 由Model,View,Controller三部分組成。Controller中包含後臺代碼邏輯,View是ASPX,如純HTML代碼,Model是中間層。經過上圖可得到這三部分的關係。

因此會發現MVC的改變有兩點,View變成簡單的HTML,後臺代碼移到簡單的.NET類中,稱爲控制器。

如下是ASP.NET MVC 請求流的通用步驟:

Step 1:首先獲取控制器。

Step 2:依賴行爲控制器建立Model對象,Model經過轉換調用數據訪問層。

Step 3:數據填充Model以後,傳遞到View 顯示層,實現顯示的目的。

clip_image012

到這裏咱們就已經瞭解了ASP.Net MVC的各個組件。下面咱們作一些小的實驗深刻了解MVC的各組件。首先咱們從Controller 控制器開始,由於Controller是MVC體系架構的核心部分。

你是否真的理解Asp.Net MVC的Controller(控制器)?

爲了咱們可以更好的理解Controller,咱們首先須要理解Controller中涉及的專業術語:用戶交互邏輯。

什麼是用戶交互邏輯?

場景1

你是否想過當用戶輸入URL摁下回車鍵時,會發生什麼事情?

clip_image013

瀏覽器首先須要給服務器發送請求,服務器再作出響應。

clip_image014

經過這些請求以後,客戶端正嘗試與服務器交互,服務器可以反饋響應,由於服務器端存在一些判斷邏輯來處理這些請求。這些可以處理用戶請求以及用戶交互行爲的業務邏輯稱爲用戶交互邏輯。

場景2

有一種常見的狀況,服務器端發送的請求是HTML請求。HTML請求是由一組輸入控件和提交按鈕組成的。

clip_image015

當用戶點擊「Save」按鈕以後會發生什麼?

若是你的回答是有一些事件處理器來處理button點擊事件,那麼很抱歉回答是錯誤的。

在Web編程中是沒有事件的概念的,Asp.net Web forms 根據咱們的行爲自動添加了處理代碼,因此給咱們帶來的錯覺認爲是事件驅動的編程。這只是一種抽象的描述。

當點擊Button時,一個簡單的HTTP請求會發送到服務器。差異在於Customer Name,Address以及Age中輸入的內容將隨着請求一塊兒發送。最終,若是是有個請求,服務器端則有對應的邏輯,使服務器可以更好響應請求。簡單來講是將用戶交互邏輯寫在服務器端。

在Asp.Net MVC中,C表明Controller,就是用來處理用戶交互邏輯的。

實驗一:簡單的MVC Hello world,着重處理Controller。

  • Step1 建立一個Asp.Net MVC 5項目

打開Visual studio 2013 點「文件」->新建->項目。

clip_image016

  • Step 1.2 選擇Web 應用,輸入項目名稱,選擇存放路徑,點擊肯定。

clip_image017

  • Step 1.3 選擇MVC 模板

clip_image018

  • Step 1.4 選擇Change Authentication(改變受權),彈出對話框中選擇「No Authentication」,並點擊肯定。

clip_image019

  • Step 2 –建立控制器
  • Step 2.1,在資源管理器中,右擊controller文件夾,選擇添加->Controller(控制器)

clip_image020

  • Step 2.2 選擇空 MVC 5 Controller 並點擊添加

clip_image021

  • Step 2.3 輸入控制器的名稱」TestController「,點擊添加。

在這一步驟中,要特別注意千萬不能刪除名稱中的」 Controller」關鍵字。名稱中必須包含Controller關鍵字。

clip_image022

  • Step 3. 建立行爲方法

打開新建的TestController 類,能夠發現已生成的Index 方法,將該方法刪除,而且添加新方法命名爲GetString ,代碼以下:

1:  public class TestController : Controller
2:  {
3:      public string GetString()
4:     {        return "Hello World is old now. It’s time for wassup bro ;)";
5:
6:    }
7:  }
  • Step 4. 運行並測試 按 F5 鍵,在地址欄中以「ControllerName/ActionName」這樣的形式輸入,須要注意的輸入控制器名稱時,不能輸入」Controller「只輸入」Test」。

clip_image023

 

實驗一:Q&A

1. TestController 和Test之間的關係是什麼?

TestController是類名稱,而Test是Controller的名稱,請注意,當你在URL中輸入controller的名稱,不須要輸入Controller這個單詞。

2. Action(行爲) 方法是什麼?

Action 方法 簡單的來講就是一個Controller內置的public類型的方法,可以接收並處理用戶的請求,上例中,GetString 方法返回了一個字符串類型的響應。

注意:在Asp.Net Web Forms中默認的返回請求是HTML的,若是須要返回其餘類型的請求,就必須建立HTTP 處理器,重寫內容類型。這些操做在Asp.net中是很困難的。在Asp.net MVC中是很是簡單的。若是返回類型是」String「直接返回,不須要發送完整的HTML。

3. 若是從Action 方法中返回對象值會出現什麼意外狀況?

請瀏覽如下代碼

1:  namespace WebApplication1.Controllers
2:  {
3:      public class Customer
4:      {
5:          public string CustomerName { get; set; }
6:          public string Address { get; set; }
7:      }
8:      public class TestController : Controller
9:      {
10:          public Customer GetCustomer()
11:          {
12:              Customer c = new Customer();
13:              c.CustomerName = "Customer 1";
14:              c.Address = "Address1";
15:              return c;
16:          }
17:      }
18:  }

 輸出結果以下所示: 

 

 

clip_image024
當返回類型如「Customer」這樣相似的對象時,將調用ToString()方法,返回「NameSpace.ClassName」形式的類名。

4. 若是須要得到上面例子中的屬性值,要如何操做?

簡單重寫類的「ToString」方法,以下:

1:  public override string ToString()
2:  {
3:       return this.CustomerName+"|"+this.Address;
4:  }

 

 

運行結果:

clip_image025

5. Action 方法是否只能用Public修飾符來修飾?

答案是確定的,每一個公有方法都會自動稱爲Action 方法。

6. 非public方法是什麼?

類的方法都比較簡單,而且並非公共可用的。沒法在Web中調用。

7. 若是咱們須要其餘函數來完成一些特定功能,但不是Action Method要如何實現?

使用NonAction屬性修飾,以下:

 

 

1:  [NonAction]
2:  public string SimpleMethod()
3:  {
4:     return "Hi, I am not action method";
5:  }

 

 

當嘗試給以上Action 方法發送請求時,會得到如下結果: 

clip_image026

View部分

Controller是處理用戶請求,並作出響應,一般狀況下響應都是以顯示在瀏覽器中,使用HTML代碼,瀏覽器纔可識別。HTML有圖像,文本,輸入控件等。一般稱爲用戶界面的設計即UI層,在ASP.net MVC稱爲View。

實驗二——深刻理解View

在實驗二中,建立一個簡單的MVC應用,僅僅具備Controller和簡單的字符串類型的返回值。讓咱們來了解MVC中的View部分吧。

  • Step1 –建立新的Action 方法

在TestController中添加新的Action 方法,以下:

1:  public ActionResult GetView()
2:  {
3:     return View("MyView");
4:  }

 

  • Step 2 建立View
  • Step 2.1 右擊上述建立的Action 方法,選擇「添加View」

 

clip_image027

  • Step 2.2 在添加View的對話框中輸入View名稱「MyView」,取消選擇「使用佈局」的複選框,點擊添加。

clip_image028

資源管理器重的Views/Test文件夾中會添加一個新的View文件。

clip_image029

  • Step3 在View中添加內容

打開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>
  • Step 4. 運行 按F5鍵運行應用

clip_image030

實驗二:Q&A

1. 爲何View會放在Test的文件夾中?

View是與放置在特定目錄下的Controller相關。這個特定文件夾是以」ControllerName」命名的,而且放在View文件夾內

2. 在多個控制器中沒法重用View嗎?

固然能夠,咱們須要在將這些文件放在特定的Shared文件夾中。將View 放在Shared文件夾中全部的Controller均可用。

clip_image031

3. 單個Action 方法中可引用多個View嗎?

能夠,ASP.NET MVC的view和Controller不是嚴格的匹配的,一個Action Method能夠引用多個view,而一個View也能夠被一個Action方法使用以下代碼所示:

1:  public ActionResult GetView()
2:  {
3:      if(Some_Condition_Is_Matching)
4:      {
5:         return View("MyView");
6:      }
7:      else
8:      {
9:         return View("YourView");
10:      }
11:  }

 

 

4. View函數的功能是什麼?

 建立 ViewResult 對象將會渲染成視圖來給用戶反饋

 

  • ViewResult 建立了ViewPageActivator 對象
  • ViewResult 選擇了正確的ViewEngine,而且會給ViewEngine的構造函數傳ViewPageActivator對象的參數
  • ViewEngine 建立View類的對象
  • ViewEngine 調用View的RenderView 方法。

5. ActionResult和 ViewResult的關係是什麼?

ActionResult是抽象類,而ViewResult是ActionResult的多級孩子節點,多級是由於ViewResult是ViewResultBase的子類,而ViewResultBase是ActionResult的孩子節點。

6. 什麼是ContentResult?

ViewResult是HTML響應而ContentResult是標準的文本響應,僅返回字符串類型。區別就在於ContentResult是ActionResult的子類。

通過了本節MVC基礎知識的學習,相信你們對MVC已經有了基本的認識。你們在進行ASP.NET MVC的開發時,還能夠藉助一些開發工具。ComponentOne Studio ASP.NET MVC 是一款輕量級控件,與Visual Studio無縫集成,徹底與MVC6和ASP.NET 5.0兼容,將大幅提升工做效率。

相關文章
相關標籤/搜索