1. 程式人生 > >七天學會ASP.NET MVC ——深入理解ASP.NET MVC

七天學會ASP.NET MVC ——深入理解ASP.NET MVC

pow rdquo www turn iter 業務邏輯 activator 過去的 界面

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

技術分享

系列文章

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

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

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

七天學會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。

我們可將原來的ASP.NET稱為 ASP.NET Webforms,新的MVC 稱為ASP.NET MVC.

ASP.NET Web Form

ASP.NET 在過去的十二年裏,已經服務並成功實現Web 應用的開發。我們首先了解一下為什麽ASP.NET能夠如此流行,並成功應用。

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

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

技術分享

因此微軟的可視化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快了兩倍。

技術分享

接下來我們在思考一個問題為什麽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:  }

運行結果:

技術分享

如果查看HTML輸出,則會顯示如下代碼:

<input name="TextBox1" type="text" value="Make it simple" id="TextBox1" style="" />

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

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

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

技術分享

通過分析我們可以得知,每一次請求都有轉換邏輯,運行並轉換服務器控件為HTML輸出。如果我們的頁面使用表格,樹形控件等復雜控件,轉換就會變得很糟糕且非常復雜。HTML輸出也是非常復雜的。由於這些不必要的轉換從而增加了響應時間。該問題的解決方案就是擺脫後臺代碼,寫成純HTML代碼。

帶寬消耗

ASP.NET開發人員都非常熟悉Viewstates,因為它能夠自動保存post返回的狀態,減少開發時間。但是這種開發時間的減少會帶來巨大的消耗,Viewstate增加了頁面的大小。在做的加載測試中,與MVC 對比,我們發現Viewstate增加了兩倍的頁面存儲。以下是測試結果:

技術分享

頁面尺寸的增加是因為viewstate產生了額外的字節。下圖就是Viewstate的截圖。許多人可能會不同意此觀點,但是眾所周知,開發人員是如何工作的,如果有選擇,他們肯定會采取別的選擇。

技術分享

  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存在的兩大問題即服務器控件和後臺代碼,以下是根源圖,

技術分享

那麽解決方案是什麽?

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

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

技術分享

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

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

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

技術分享

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 顯示層,實現顯示的目的。

技術分享

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

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

為了我們能夠更好的理解Controller,我們首先需要理解Controller中涉及的專業術語:用戶交互邏輯。

什麽是用戶交互邏輯?

場景1

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

技術分享

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

技術分享

通過這些請求之後,客戶端正嘗試與服務器交互,服務器能夠反饋響應,因為服務器端存在一些判斷邏輯來處理這些請求。這些能夠處理用戶請求以及用戶交互行為的業務邏輯稱為用戶交互邏輯。

場景2

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

技術分享

當用戶點擊“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 點“文件”->新建->項目。

技術分享

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

技術分享

  • Step 1.3 選擇MVC 模板

技術分享

  • Step 1.4 選擇Change Authentication(改變授權),彈出對話框中選擇“No Authentication”,並點擊確定。

技術分享

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

技術分享

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

技術分享

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

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

技術分享

  • 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”。

技術分享

實驗一: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:  }

輸出結果如下所示:

技術分享
當返回類型如“Customer”這樣類似的對象時,將調用ToString()方法,返回“NameSpace.ClassName”形式的類名。

4. 如果需要獲得上面例子中的屬性值,要如何操作?

簡單重寫類的“ToString”方法,如下:

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

運行結果:

技術分享

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 方法發送請求時,會獲得以下結果: 

技術分享

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”

技術分享

  • Step 2.2 在添加View的對話框中輸入View名稱“MyView”,取消選擇“使用布局”的復選框,點擊添加。

技術分享

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

技術分享

  • 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鍵運行應用

技術分享

實驗二:Q&A

1. 為什麽View會放在Test的文件夾中?

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

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

當然可以,我們需要在將這些文件放在特定的Shared文件夾中。將View 放在Shared文件夾中所有的Controller都可用。

技術分享

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兼容,將大幅提高工作效率。

下一節,我們將討論模型,驗證,Jquery和Json。所以請持續關註吧!ComponentOne Studio!

原文鏈接:http://www.codeproject.com/Articles/866143/Learn-MVC-step-by-step-in-days-Day

相關閱讀:

是什麽讓C#成為最值得學習的編程語言

從Visual Studio看微軟20年技術變遷

C#開發人員應該知道的13件事情

Visual Studio 2017正式版發布全紀錄

七天學會ASP.NET MVC ——深入理解ASP.NET MVC