iT邦幫忙

DAY 12
0

以Asp .Net MVC 5 為基礎,建立自己的程式開發框架系列 第 12

BaseController的重要性

在這一篇將會介紹為什麼對框架來說有一個BaseController讓所有的Controller來繼承很重要,並且介紹一個簡單的強型別的RedirectToAction讓所有繼承這個BaseController的可以來使用。

透過這個強型別的RedirectToAction讓在寫Code的時候,不要犯下寫錯Action的名字,或者Action名字改了但是對應的RedirectToAction沒有改到的低級錯誤。

為什麼要自定自己的BaseController

所有的Controller都會繼承System.Web.Mvc.Controller。繼承的概念在OO裡面很重要,因為可以讓一些所有Controller都通用的功能,透過繼承來傳下去。同時,一些特殊的Attribute如果放在Controller的層級,那麼所有的ActionResult都會有效果,因此針對我們的框架,就會定義一個框架的BaseController來讓所有的Controller繼承,以提供一些通用的方法。

同步發表於我的部落格:http://alantsai2007.blogspot.com/2014/10/BuildYourOwnApplicationFrameworkOnMvc-12-importantofbasecontroller.html

強型別的RedirectToAction

定義一個BaseController非常的簡單,只需要定一個class然後讓他繼承System.Web.Mvc.Controller,之後我們實際要使用的Controller在繼承這個BaseController 就可以了。

/// <summary>
/// Application 層級的BaseController
/// </summary>
public class BaseController : Controller
{
}
 
// 繼承BaseController
public class HomeController : BaseController
{
}

為了未來的擴充性,因此就算目前沒有任何共通的方法而讓BaseController留空都沒關係,因為有了這一層,在未來需要添加內容就會變的相對簡單。

不過為了不讓我們的BaseController什麼都沒有,我們來做一個很好用的功能,那就是加入強型別的RedirectToAction。

那什麼是強型別的RedirectToAction?基本上Controller已經有一個RedirectToAction的方法,不過這個方法和很多Mvc的helper方法一樣,接受一個string作為參數,而這個string就是所謂的「magic string」會幫我們對應到正確的Action。舉例來說,通常儲存成功都會做一個RedirectToAction("Index"),表示回傳的內容將會是這個Controller的IndexActionResult。

問題來了,假設今天打的太快,把「Index」打成「Indx」(或者是把Action從「Index」改成了「Home」但是忘記改對應的RedirectToAction),因為它是string,在compile time完全看不出來打錯了。只有到Runtime才會發現有問題。那這個地方就有可能被漏掉並且造成系統炸掉,如果剛好在客戶面前發生,那麼整個開發團隊感覺就low掉了。

少打一個字母,其實肉眼很不容易發現

而強型別的RedirectToAction就可以避免掉這個問題。

取得和使用強型別的RedirectToAction

有一個Nuget的package叫做:Microsoft.AspNet.Mvc.Futures。

可以透過Package Mangement Console輸入:Install-Package Microsoft.AspNet.Mvc.Futures來安裝。

這個Package就有包含一個強型別的RedirectToAction,不過它屬於extension method,因此使用起來有些變扭:

// 繼承BaseController
public class HomeController : BaseController
{
    public ActionResult Index()
    {
        return View();
    }
 
    public ActionResult Create()
    {
        ...
        return this.RedirectToAction<HomeController>(x => x.Index());
    }
}

這個強型別的RedirectToAction是很好,可是用起來都需要加上this實在和原始的RedirectToAction感覺不一樣,難道沒有辦法讓呼叫強型別的時候,不要透過this?這時候我們的BaseController就能夠排上用場。

BaseController讓強型別的RedirectToAction用起來和原來的版本一樣

我們可在BaseController做一個Wrapper,把那個extension方法包起來,這樣呼叫起來感覺強型別的RedirectToAction就和原本的是一樣的呼叫方式:

/// <summary>
/// Application 層級的BaseController
/// </summary>
public class BaseController : Controller
{
    /// <summary>
    /// Redirects to action.
    /// </summary>
    /// <typeparam name="TController">The type of the controller.</typeparam>
    /// <param name="action">The action.</param>
    /// <returns></returns>
    protected ActionResult RedirectToAction<TController>(Expression<Action<TController>> action)
        where TController : Controller
    {
        return ControllerExtensions.RedirectToAction(this, action);
    }
}
 
// 繼承BaseController
public class HomeController : BaseController
{
    public ActionResult Index()
    {
        return View();
    }
 
    public ActionResult Create()
    {
  ...
        return RedirectToAction<HomeController>(x => x.Index());
    }
}

這邊有一點需要注意,假設Index需要傳入參數,這個強型別的方法是會有問題。

結語

希望透過這個例子,能夠展示出有一個共通的Base是很好的一件事情,就算目前不需要擴充,但是只要所有的都繼承這個Base,以後要擴充就很方便。

同時希望透過介紹強型別的RedirectToAction讓在寫Code的時候,避免掉低級錯誤,像是打錯字,或者改名字沒有改到對應的「Magic String」


上一篇
傳遞資訊到前端的通用型服務
下一篇
Service層 - 概念篇
系列文
以Asp .Net MVC 5 為基礎,建立自己的程式開發框架30

1 則留言

0
juben
iT邦新手 4 級 ‧ 2014-10-05 00:20:16

原來有"強型別的RedirectToAction"啊~~~
立馬來去安裝XD

Alan Tsai iT邦新手 3 級 ‧ 2014-10-05 21:14:47 檢舉

其實這個library裡面也有包含強型別的HtmlHelper,例如強型別的ActionLink。
要使用的話,基本上就是在View裡面加上:

&lt;pre class="c" name="code">@using Microsoft.Web.Mvc

然後一般的:

&lt;pre class="c" name="code">@Html.ActionLink

就會多出強型別的helper。

不過,這些強型別的方法沒有預設就提供在Mvc裡面因為有些會有一點小問題。
以強型別的Action helper來說,有人有提出幾個小問題:
http://stackoverflow.com/questions/911019/why-strongly-typed-html-actionlink-is-not-in-asp-net-mvc-1

因此,使用的時候也要注意一下。

我要留言

立即登入留言