精進 ASP.NET MVC 開發技術,打造高生產力與易於維護的系統 (Develop ASP.NET MVC Better)


  1. 目錄
    1. Customizing routes with attribute routing
    2. Reuse View with AjaxRequest
    3. Custom Html Helper To reuse code
      1. Razor Helper
      2. Razor Function
      3. Html Helper Extension
    4. Less Responsibility On View, More Responsibility For ViewModel
    5. Seperation Concerntion of Controller & Model (Abstract Service Level)
    6. AutoFac Dependency Injection
    7. ELMAH - Log & Monitor

本次的筆記是從 LinkedIn Learing 課程中,反芻學習內容整理而成,深信只有動手輸出,才能夠將知識真正納為己有 😉

logo

目錄

Customizing routes with attribute routing

在 RouteConfig.cs 加入 routes.MapMvcAttributeRoutes

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapMvcAttributeRoutes();

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

即可在 Controller Action 藉由 Route Attribute 自定義路由,使用 Url.Action 的 Url 會自動配合使用新的 Route ,十分方便。

Controller.cs

[RoutePrefix("Home")]
public class HomeController : Controller
{
    [Route("~/About")] // /About/
    [Route] // /Home/
    [Route("~/")] // /
    [Route("Information")] // /Home/Information/
    [Route("Info/About")] // /Home/Info/About
    public ActionResult About()
    {
        return View();
    }
    
    [Route("Application")] // /Home/Contact -> /Home/Application/
    public ActionResult Contact()
    {
        return View();
    }
}

Route Constraint 可以進一步的限制參數條件來決定使用不同的 Action 處理。

Controller.cs

[Route(@"~/Route/{str:regex(^\d{6})}")]
public ActionResult ProcessDigits(string str)
{
    return Content($"<h1>It's Digit</h1><p>{str}</p>");
}

[Route(@"~/Route/{str:regex(^[a-zA-Z]\d{0,8})}")]
public ActionResult ProcessAlphaDigits(string str)
{
    return Content($"<h1>It's Alpha Digit String</h1><p>{str}</p>");
}

MS Docs - Route Constraints

Reuse View with AjaxRequest

共用 Controller Action 及 View,利用 IsAjaxRequest 區別呼叫是否來自於 Ajax,如果是以 Partial View 方式回傳,避免多餘的 head, body 標籤。

Custom Html Helper To reuse code

重複使用 Razor Html Code 的三種方式:

  1. Razor Helper
  2. Razor Function
  3. Html Helper Extension

Razor Helper

/cshtml

@helper ROCCalendarTrans(int commonEra)
{
    <text>@(commonEra - 1911)</text>
}

@ROCCalendarTrans(DateTime.Now.Year)

@helper AMPM(DateTime datetime)
{
    if (datetime.Hour < 12)
    {
        <text>AM🌞</text>
}
    else
    {
        <text>PM🌙</text>
    }
}

@AMPM(DateTime.Now)

Razor Function

/cshtml

@functions
{
    public int func(string str)
    {
        return 42;
    }
}

@func("params")

不論是 Razor Helper 或者 Function 都可以將程式碼存在 App_Code 讓 View 共用,引用的方式配合調整為檔案名稱即可。例如 App_Code/RazorHelper.cshtml 下則調整為 @RazorHelper.HelperName 😎

Html Helper Extension

/App_Code/HtmlHelperExteinsions.cs

namespace System.Web.Mvc
{
    public static MvcHtmlString ExtensionExamples(this HtmlHelper helper, object htmlAttributes = null)
    {
        var ele = new TagBuilder("div")
        {
            InnerHtml = "<p>Lorem Ipsum</p>"
        };
        ele.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
            
        return new MvcHtmlString(ele.ToString());
    }
}

GitHub - Nancy.ViewEngines.Razor.HtmlHelpers

目前範例寫得還不理想,主要是要用 TagBuilder 客製化可以重用的 Html Code,待實際情境再補充這部分的內容 🤔

Less Responsibility On View, More Responsibility For ViewModel

View 中複雜的邏輯抽取為 ViewModel 的方法。

  1. 不要懼怕創造新的類別(Viewmodel),為了區別輸入物件與呈現物件,使用不同的類別是可以被接受的
  2. 類別共有屬性,藉由 Controller 做 Adapter 轉換兩者
  3. Viewmodel 中可以將原本 View 的 logic 抽取出

Seperation Concerntion of Controller & Model (Abstract Service Level)

將 Controller 中龐雜的邏輯抽取為 Business Folder 下的 Service.cs

AutoFac Dependency Injection

ELMAH - Log & Monitor

The Error Logging Modules And Handlers

Nuget Install :

Install-Package elmah
Install-Package elmah.xml
Install-Package elmah.mvc

預設情況下,ELMAH 會將錯誤存在 Ram 中,安裝完成 elmah.xml packages 後,則會將資料存在 ~\App_Data\Elmah.Errors 下以 XML file 的方式保存。每一個 XML file 代表一個 錯誤。

使用 ELMAH 要特別注意存取的安全性,因為錯誤訊息的資料如果被惡意存取,將會被利用於攻擊所使用。

同時 ELMAH 可以將資料改存在資料庫,另外可以設定電子郵件通報以及區別事件的等級來決定是否通報。