天天看點

[譯]Asp.net MVC 之 Contorllers(一)

Asp.net MVC contorllers

    在Ajax全面開花的時代,ASP.NET Web Forms 開始慢慢變得落後。有人說,Ajax已經給了Asp.net緻命一擊。Ajax使越來越多的控制在Html和用戶端代碼完成。随着時間的推移,導緻了架構的變化,也使ASP.NET Web Forms有點不能适應當今潮流。

    基于目前的ASP.NET運作時環境和MVC模式,誕生了一個新的架構——ASP.NET MVC,這種組合的Web開發模式順應了當今的開發的趨勢。

    在ASP.NET MVC中,每一個請求最終就是執行一個特殊類中的Action方法。Action的執行結果被傳遞給帶有視圖模版的視圖子系統中。浏覽器最終的響應結果就是由Action的執行結果和這個模版建立的。

    與Web Forms不同,ASP.NET MVC是由各個層的代碼連接配接在一起的,這些層次之間既不是互相交叉,也不是單一一坨的子產品。正因如此,根據自定義元件能很輕松的替換其中任何一層,這樣就提高了解決方案的可維護性和穩定性。使用ASP.NET MVC,不僅有标簽的完全控制權,還可以使用樣式和喜歡的js架構。

    盡管你想堅持使用Web Froms,但是對于當今的Web開發來說,ASP.NET MVC 确實是一個更好的選擇。我們不需要花費太多的時間去學習,但是我們必須知道怎麼運用以及MVC工作原理。如果這樣做了,那麼我們投入将會快速的帶給我們應有的回報。

    注:本系列是基于ASP.NET MVC 5。該版本是向前相容的,也就是說,一台電腦中可以同時安裝新老版本,新版本運作不會影響現存MVC版本代碼。

路由請求

    最初,ASP.NET平台的開發主要是圍繞着伺服器端實體頁面請求的思想。在ASP.NET應用程式中使用的大多數的URL是由兩部分組成:包含邏輯的實體網頁的路徑,和一些填充在查詢字元串中的作為參數的資料。這種方式已經使用了有些年了,現在仍在被使用。ASP.NET運作時環境沒有限制我們隻能調用特定位置或者檔案的資源。通過寫一個專門的HTTP處理程式,并綁定到URL,我們就可以使用ASP.NET響應一個非依賴于實體檔案的請求執行代碼。這隻是ASP.NET MVC不同于ASP.NET Web Forms衆多不同中的一個方面。接下來我們看看如何通過使用一個HTTP處理程式來模拟ASP.NET MVC行為。

    注:在軟體中,專業術語URI(Uniform Resource Identifier)是用于通過位置或名稱來引用的資源。當URI通過位置來辨別資源時,就是URL(Uniform Resource Locator)。當URI通過名稱辨別資源時,就變成了URN(Uniform Resource Name)。在這方面,ASP.NET MVC是設計來處理更通用的URI,而ASP.NET Web Forms被設計來處理位置識别實體資源。

模拟ASP.NET運作時

    我們建構一個簡單的ASP.NET Web Forms應用程式,使用HTTP處理程式搞清楚ASP.NET MVC應用程式的内部機制。我們從最基本的ASP.NET Web Forms應用程式開始。

定義辨認URLs的文法

    請求的URLs不需要比對伺服器端的實體檔案。第一步列出應用程式有意義的URLs。為了避免太特殊,我們假設支援幾個固定的URLs,把他們映射到一個HTTP處理程式子產品。下面的代碼片段顯示了請求中預設Web.config的變化

[譯]Asp.net MVC 之 Contorllers(一)
[譯]Asp.net MVC 之 Contorllers(一)
<system.web>
    <httpHandlers>
      <add verb="*" path="home/test/*" type="MvcEmule.Components.MvcEmuleHandler"/>
    </httpHandlers>
  </system.web>      

MvcEmuleHandler

    隻要應用程式收到一個與配置中比對的URL請求,就會轉到相應的處理程式。

定義HTTP處理程式行為

    在ASP.NET中,HTTP處理程式是一個實作了IHttpHandler接口的元件。非常簡單,隻有兩個成員,代碼如下:

[譯]Asp.net MVC 之 Contorllers(一)
[譯]Asp.net MVC 之 Contorllers(一)
public class MvcEmuleHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            // 業務邏輯
        }

        public Boolean IsReusable
        {
            get { return false; }
        }
    }      

public class MvcEmuleHandler : IHttpHandler

    大多數時候,HTTP處理程式是根據輸入資料的查詢字元串傳遞(query string)相關的寫死行為。然而,他不能阻止我們使用請求處理程式最為抽象工廠,增加一個或多個簡介層。事實上,我們可以使用請求處理程式中的請求資訊,來确定外部的實際服務請求。按照這種方式,一個簡單的HTTP請求程式可以服務于大量的請求,隻要調用一些更加專門的元件。

HTTP 處理程式可以解析出 URL中的标記(Controller、action、param),并使用該資訊來辨別類和調用的方法。下面是它如何工作的示例:

[譯]Asp.net MVC 之 Contorllers(一)
[譯]Asp.net MVC 之 Contorllers(一)
public void ProcessRequest(HttpContext context)
        {
            // 轉化 URL 并擷取 controller, action, 和參數
            var segments = context.Request.Url.Segments;
            var controller = segments[1].TrimEnd('/');
            var action = segments[2].TrimEnd('/');
            var param1 = segments[3].TrimEnd('/');

            // 使用字首和命名空間組裝Controller類名
            var fullName = String.Format("{0}.{1}Controller",
            this.GetType().Namespace, controller);
            var controllerType = Type.GetType(fullName, true, true);

            // 執行個體化controller
            var instance = Activator.CreateInstance(controllerType);

            // 調用 controller 執行個體的 action 方法 
            var methodInfo = controllerType.GetMethod(action,
            BindingFlags.Instance |
            BindingFlags.IgnoreCase |
            BindingFlags.Public);
            var result = String.Empty;
            if (methodInfo.GetParameters().Length == 0)
            {
                result = methodInfo.Invoke(instance, null) as String;
            }
            else
            {
                result = methodInfo.Invoke(instance, new Object[] { param1 }) as String;
            }

            // 傳回結果
            context.Response.Write(result);
        }      

public void ProcessRequest(HttpContext context)

    我們假設上面的代碼中,伺服器名稱後面的第一個标記,唯一辨別了服務請求的元件(類)。第二個标記涉及這個元件(類)中需要調用的方法名最後,第三個标記辨別傳遞的參數

請求HTTP處理程式

    在浏覽器中輸入一個URL http://localhost:9086/home/test/*,他的結果就是,“home”辨別了類名,“test”辨別方法名,無論結尾是什麼,都作為參數。類型進一步制定,擴充為包含命名空間和字尾。根據執行個體,,最終類名是MvcEmule.Components.HomeController。預計這個類對于應用程式是可用的,也暴露一個名為Test的方法。看下結果:

[譯]Asp.net MVC 之 Contorllers(一)
[譯]Asp.net MVC 之 Contorllers(一)
public class HomeController
    {
        public String Test(Object param1)
        {
            var message = "<html><h1>Got it! You passed ‘{0}’</h1></html>";
            return String.Format(message, param1);
        }
    }      

public String Test(Object param1)

[譯]Asp.net MVC 之 Contorllers(一)

    這個簡單的執行個體說明了如何使用ASP.NET MVC最基本的機制。控制器(Controller)是一個為請求提供服務的專門的元件。控制器(Controller)是一個隻有方法沒有狀态的類。一個獨特的系統級HTTP處理程式負責将發來的請求比對到一個特定的控制器類,這樣一個類的執行個體将執行一個給定的操作方法,并産生一個響應。

    那麼Url 的方案是怎樣呢?在此示例中,我們隻是使用寫死的 URL。在 ASP.NET MVC 中,有一種非常靈活的文法,可以使用表示應用程式能夠識别的這些 Url。此外,一個新的系統元件在運作時管道中截取的請求、 處理 URL,并觸發的 ASP.NET MVC HTTP 處理程式。此元件是 URL 路由的 HTTP 子產品。關于URL路由子產品,下次再譯。