使用Autofac和Unity學習MVC 4,5和Web API 1,2的IoC,DI技巧

IoC與DI

IoC
Inversion of control,中文稱控制反轉。由Martin Fowler提出。這裡引用MVP 91哥的說明:系統架構設計應該以抽象的邏輯概念為主,才能更貼近現實世界,才能更符合domain model,當Business logic不變時,需求變更、技術變更、DB變更,都應該要把風險和成本壓到最低。
DI
Dependency injection,中文稱相依注入。在IoC的思考模式與實作下,最終的結果就是相依於介面(Interface),但類別中最後只存有介面的話,程式是不會動的,這時我們就會利用DI技巧,在應用程式啟動時去注入介面所對應的實體(也就是一般我們在程式碼裡寫的new ClassName())。

MVC與Web API的Controller的IoC與DI處理

不管是在ASP.NET MVC或ASP.NET Web API,在Controller的概念上或本質上可以說是一模一樣。這裡主要差異點會是在DI套件的實作差異上。

Controller使用Respository Pattern處理資料實體相依

一般我們會透過基架(MVC 5將scaffold翻譯為基架)來產生MVC的Controller與View Page,或是Web API的API Controller。例如,使用Northwind資料庫的Product資料表來產生API Controller會是這樣:

  public class ProductsController : ApiController
  {
      private NorthwindEntities db = new NorthwindEntities();

      // GET api/Products
      public IEnumerable<Product> GetProducts()
      {
          return db.Products.AsEnumerable();
      }

      // 省略
  }
  

預設範本所產生的程式碼會產生與NorthwindEntities資料實體(new NorthwindEntities())產生依賴關係。每個API Controller都還要處理db.Products,這造成API Controller的職責不夠單一,這在裡我們就先採用Repository Pattern 1來分離資料庫處理程式碼與API Controller的相依關係。

1 Repository Pattern實作請參考《ASP.NET MVC 4網站開發美學》第七章 Page 7-40頁。

  public class ProductsController : ApiController
  {
      //private NorthwindEntities db = new NorthwindEntities();

      private IProductRepository _product;

      public ProductsController() {
          _product = new ProductRepository();
      }

      // 重要,但要等一下才會知道
      public ProductsController(IProductRepository r)
      {
          _product = r;
      }

      // GET api/Products
      public IEnumerable<Product> GetProducts()
      {
          return _product.GetAll();
      }

      // 省略
  } 
  

透過Repository Patter我們分離了資料庫相關程式碼,而且我們偷偷留下一個含介面參數的建構函式,等一下在討論這部分。就目前使用了Repository Pattern的Controller,就算刪除此含介面參數的建構函式,程式依然會正常運作。

但引入使用Repository Pattern後的API Controller產生了新的問題,這些API Controller又會與特定實體類別產生相依關係,我們必須在無參數建構函式去初始化一個實體類別,以呼叫分離後的資料庫處理程式(例如:_product = new ProductRepository();)。

DOM修改文字節點 - innerText或textContent傻傻分不清楚

textContent=innerText?

DOM節點樹

圖片來源:www.w3schools.com

在一段JS程式碼之中,看到一個未看過的textContent屬性,查詢了一下依照MDN對textContent的說明:Gets or sets the text content of a node and its descendents.基本上它的使用方式和innerText屬性一樣。

innerText與textContent的差異?

如果你對DOM不熟悉,可以先參考這篇DOM簡介

就功能上而言,兩者是一模一樣,主要都是針對文字節點(Text Node)來進行get與set的動作。先看一下以下程式碼:

   <!DOCTYPE html>
   <html>
   <head>
   <meta charset=utf-8 />
   <title>Text Node Test</title>
   </head>
   <body>
     <p id="help1"></p>
     <p id="help2"></p>
     <p id="help3"></p>
   </body>
   </html>
  

以上只是一個簡單包含三個空白<p>元素的HTML。然後,我們撰寫JavaScript來修改文字節點的內容:

表格的欄位為什麼不對齊

表格的欄位為什麼不對齊

表格的欄位不對齊

Table Display Bug

這是一個舊頁面內容,裡面的本來都很正常。但近來有使用者慢慢更新作業系統或瀏覽器後,發現表格原本被隱藏的欄位在點擊後不會正常排版。各位可以點擊標題測試,如果你是舊IE 6~IE 9,以上測試是正常的。但從IE 10開始,上述表格欄位就會不正常。(包含目前主流瀏覽器都不正常)

MVC練習 - 依使用者選擇時區顯示該時區時間

MVC練習

假日看到MVP Edward.K一篇[ASP.NET]利用TimeZoneInfo將現在時間切換到各個國時間一文,覺得介紹的很不錯。就改寫為MVC的版本,自我練習一下。

ZoneController

新增一個ZoneController,此Controller要取得時區清單並傳遞至View Page。MVC 5的加入控制器和之前有些不同:

MVC 5 - 添加基架

Scaffold在MVC 5正式反翻為「基架」之不是之前Preview與RC的「支架」。選擇使用「MVC 5控制器-空白」。

在ZoneController新增一個名稱Time的Action方法:

   public ActionResult Time()
   {
       IReadOnlyCollection<TimeZoneInfo> timeZones = TimeZoneInfo.GetSystemTimeZones();
       ViewBag.TimeZoneInfo = new SelectList(timeZones, "Id", "DisplayName");
       return View();
   }
  

IReadOnlyCollection本身繼承IEnumerable與IEnumerable(Of T),可以直接將取得的timeZones傳入SelectList類別使用。在SelectList類別選擇使用第三種建構函式:「SelectList(IEnumerable, String, String)」:

使用Entity Framework Code first建立多對多關係

Code First

Code First中文可以稱「程式碼先行」或「程式碼優先」,在Entity Framework 4.1時正式支援,它與一般開發習慣不同,先透過程式碼來定義資料結構(一般是POCO,Plain Old CLR Object),定義完成之後即可開始進行開發工作。在開發進行過程,開發人員不用管資料庫之類的問題,Entity Framework會進行處理,開發人員只要專注處理POCO與邏輯程式碼身上。

多對多關係?

多對多關係(Many-To-Many)是指資料兩者之間的關係是多對多,例如,醫生與病人,一個醫生會醫治多個病人,一個病人依病情不同也會有多個醫生來治療(會診即是一種),這種關係在資料庫領域稱多對多關係(Many-to-Many)。

有一點點資料庫經驗的人員都知道,實務上在資料庫中是沒有多對多資料表,多對多關係到了資料庫裡會化成三張資料表,分別建立成one-to-many與one-to-many的關係,以上例說明:「醫生(one)-to-醫生病人(many)」與「病人(one)-to-醫生病人(many)」,所以會有「醫生資料表」「醫生病人資料表」「病人資料表」三張資料表,中間透過「醫生病人資料表」來串接多對多關係。

ASP.NET MVC實作Code First Many-to-Many Relationship

以下我們透過ASP.NET MVC [4|5]專案來實作一次Code First的多對多關係。我們模擬的關係是「開發人員-to-專案」,一位開發人員可以同時接手多個專案,一個專案同時有多個開發人員進行開發。