1. 程式人生 > >ASP.NET MVC 入門4、Controller與Action

ASP.NET MVC 入門4、Controller與Action

本系列文章基於ASP.NET MVC Preview5.

Controller是MVC中比較重要的一部分。幾乎所有的業務邏輯都是在這裡進行處理的,並且從Model中取出資料。在ASP.NET MVC Preview5中,將原來的Controller類一分為二,分為了Controller類和ControllerBase類。Controller類繼承自ControllerBase類,而ControllerBase實現是了IController介面。

image

ControllerBase實現了IController介面的Execute方法,在Route匹配到Controller之後,就會呼叫Execute方法來進入Controller的處理。這裡還定義了一個抽象的方法ExecuteCore方法,該方法會在Execute方法的最後被呼叫。ControllerBase還定義了三個核心的屬性。我們在後面會詳細討論TempData和ViewData。

Controller類除了繼承自ControllerBase類以外,還實現了好幾個Filter介面,Filter我們在後面再詳細討論。

publicabstractclass Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter{ }


Controller類還定義很多有用的方法,我們新建的Controller都必須繼承自這個Controller類。例如我們新建一個AdminController:

publicclass AdminController : Controller
{
}

Action方法

下面談一下在Controller中比較重要的Action方法。在ASP.NET MVC中URL都是對映到Controller中的某個Action中,然後由匹配的Action來處理我們的業務邏輯並返回view的。

Controller中的public的方法都被當作是Action方法。Action方法通常返回一個ActionResult的結果。例如我們為前面的AdminController定義一個Setting的Action方法,用於設定Blog的一些基本引數:

publicclass AdminController : Controller
{
   
public ActionResult Setting()
    {
       
thrownew NotImplementedException();
    }
}

預設情況下,Action方法的方法名就是這個Action的Action名(Action名指的是Route中匹配Action方法的URL的那部分。例如url:Home/Index,其中Index就是Action名)。這裡為什麼要提到這個Action名呢?應為Action名是可以定義的,使用ActionNameAttribute來定義。請看下面的示例:

public ActionResult Setting()
{
   
thrownew NotImplementedException();
}

[ActionName(
"Setting")]
public ActionResult SaveSetting()
{
   
thrownew NotImplementedException();
}

這兩個Action方法的Action名都為"Setting",即對於url:Admin/Setting ,能同時匹配到這兩個Action方法。如果一個URL同時匹配到兩個Action方法的話,程式會丟擲一個錯誤:

image

如果我們希望這兩個Action的Action名都為Setting,Setting()就用於顯示一個表單頁面給使用者,而SaveSetting()就用於儲存使用者提交過來的表單資料,我們該怎麼做呢?我們可以利用AcceptVerbsAttribute來設定,這個Attribute用來定義Action方法會匹配指定的HttpMethod。例如下面的程式碼:

[AcceptVerbs("GET")]
public ActionResult Setting()
{
   
thrownew NotImplementedException();
}

[ActionName(
"Setting"), AcceptVerbs("POST")]
public ActionResult SaveSetting()
{
   
thrownew NotImplementedException();
}

這樣,對於HttpMethod為"GET"的客戶端請求,就會匹配到Setting()來顯示一個表單給使用者,如果使用者POST回來的表單資料,則會匹配到SaveSetting()上面去,我們就可以處理使用者POST過來的資料並儲存到資料庫。

在這裡AcceptVerbsAttribute是繼承自ActionSelectionAttribute的,我們也可以繼承自ActionSelectionAttribute來自定義自己想要實現的功能。這個我們後面會詳細講解。如果你比較心急,可以看下Asp.net Mvc Preview 5 體驗--實現ActionSelectionAttribute來判斷是否為AJAX請求而選擇不同的Action這篇文章。

如果你想將一個public的方法設定為不是Action方法,那麼你就要為該public的方法新增NonAction的Attribute:

image

Action方法的引數

例如我們要在AdminController中定義一個編輯日誌的Action方法:

public ActionResult EditPost(int? id)
{
   
thrownew NotImplementedException();
}

對於URL:Admin/EditPost/2 ,上面的引數會自動被賦值為2。ASP.NET MVC在匹配Route的時候會根據Route的設定自動為Action方法的引數賦值。所以前面的id引數會被自動賦值為2的前提是,在Route配置的時候,必須指定了id引數,例如:

routes.MapRoute(
   
"Default",                                              // Route 的名稱"{controller}/{action}/{id}",                           // 帶有引數的URLnew { controller ="Home", action ="Index", id =""// 設定預設的引數);

如果我們將Route修改為:

routes.MapRoute(
   
"Default",                                              // Route 的名稱"{controller}/{action}/{para}",                           // 帶有引數的URLnew { controller ="Home", action ="Index", para =""// 設定預設的引數);

則前面的Action方法的引數必須修改為public ActionResult EditPost(int? para){ },使Action方法的引數和Route中定義的引數名相同,ASP.NET MVC才能自動為Action方法的引數賦值。

ActionResult

Action方法返回ActionResult型別的結果。ASP.NET MVC為我們提供了幾種ActionResult的實現,如下:

  • ViewResult. 呈現檢視頁給客戶端。由View 方法返回.

  • RedirectToRouteResult. 重定向到另外一個Route。由RedirectToActionRedirectToRoute 方法返回.

  • RedirectResult. 重定向到另外一個URL。由 Redirect 方法返回.

  • ContentResult. 返回普通的內容。例如一段字串。由 Content 方法返回.

  • JsonResult. 返回JSON結果。由 Json 方法返回.

  • EmptyResult. 如果Action必須返回空值,可以返回這個結果。Controller中沒有實現的方法,可以return new EmptyResult();.

通常情況下,我們的Controller可能有一些相同的情況,例如我們在各個Controller中都有可能會在出錯或者什麼時候想要顯示一條提示資訊給使用者,或者有一些共同的資料要呈現的。這時候,我們最好就定義一個我們自己的Controller的基類:

publicclass BaseController : Controller
{
   
public BaseController()
    {

    }

   
protected ActionResult ShowMsg(List<string> msgs)
    {
       
thrownew NotImplementedException();
    }

   
public ActionResult Message()
    {
       
thrownew NotImplementedException();
    }
}

然後,其他的Controller都繼承自這個BaseController :

publicclass AdminController : BaseController
{
    [AcceptVerbs(
"GET")]
   
public ActionResult Setting()
    {
       
thrownew NotImplementedException();
    }

    [ActionName(
"Setting"), AcceptVerbs("POST")]
   
public ActionResult SaveSetting()
    {
       
thrownew NotImplementedException();
    }

   
public ActionResult EditPost(int? id)
    {
       
thrownew NotImplementedException();
    }
}
好,時間不早了,就先到這裡吧。Enjoy!Post by Q.Lee.lulu

---------------------------------------------------------------------