More

    BaseController 的重要性 (.NET MVC 5 Ch.12)

    在這一篇將會介紹為什麼對框架來說有一個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」

    Source : https://ithelp.ithome.com.tw/articles/10158057

    Recent Articles

    spot_img

    Related Stories

    Stay on op - Ge the daily news in your inbox