ASP.NET MVC 統一顯示格式 (使用 DisplayTemplate)

在 ASP.NET MVC 中所有資料格式都有預設的顯示方式(ex:DateTime 2017/12/19 下午 11:20:00、Deciaml 123457.00),有的資料格式顯示方式還會受到地區、文化、語系影響,遇到這類文化語系設定造成的畫面不一致或是預設顯示跟期望有落差時,可以在畫面上直接指定格式來統一輸出,只是畫面一多時日後維護就會遇到麻煩,面對這類需求最好的做法就是修改預設顯示格式

最近專案剛好有個統一全站畫面顯示的需求:日期格式:MM/dd/yyyy HH:mm:ss、數值格式:0,000.00(千分位,小數點兩位),我立馬想到透過 DisplayTemplate 就可以秒殺搞定,結果我忘記語法,新增 template 時 還卡了一下,所以怒紀錄一篇 哈哈

直接複寫預設顯示格式

  1. 在 Views –> Shared 資料夾中新增 DisplayTemplates 資料夾

    1addDisplayTemplates

  2. DisplayTemplates 資料夾建立以 目標資料型態 (e.g. DateTimeDecimal) 為名稱的 View

    使用時不需另外編譯

    • DateTime

      • 加入 DateTime.cshtml

        2adddatetime

        3adddatetime

      • 指定 model 型態(記得處理 null)

        @model DateTime?
        
        • 未處理 null 錯誤

          The model item passed into the dictionary is null, but this dictionary requires a non-null model item of type 'System.DateTime'.
          

          3-1nullerror

      • 依實際需求客製輸出格式

        @if (Model == null)
        {
            <span class="text-danger">No DateTime Data!!</span>
        }
        else
        {
            <span>@(((DateTime)Model).ToString("MM/dd/yyyy HH:mm:ss"))</span>
        }
        
      • 完整程式碼

        @model DateTime?
        @if (Model == null)
        {
            <span class="text-danger">No DateTime Data!!</span>
        }
        else
        {
            <span>@(((DateTime)Model).ToString("MM/dd/yyyy HH:mm:ss"))</span>
        }
        
      • 前後差異

        • 修改前

          4before

        • 修改後

          5after

    • Decimal

      • 加入 Decimal.cshtml

        6adddecimal

        7adddecimal

        • 無法加入 decimal.cshtml(可以加入 Decimal.cshtml 後再 rename)

          8decimalerror

      • 指定 model 型態(記得處理 null)

        @model decimal?
        
        • 未處理 null 錯誤

          The model item passed into the dictionary is null, but this dictionary requires a non-null model item of type 'System.Decimal'.
          

          9decimalnullerror

      • 依實際需求客製輸出格式

        @if (Model == null)
        {
            <span class="text-danger">No Decimal Data!!</span>
        }
        else
        {
            <span>@(((decimal)Model).ToString("N"))</span>
        }
        
      • 完整程式碼

        @model decimal?
        
        @if (Model == null)
        {
            <span class="text-danger">No Decimal Data!!</span>
        }
        else
        {
            <span>@(((decimal)Model).ToString("N"))</span>
        }
        
      • 前後差異

        • 修改前

          10before

        • 修改後

          11after

  3. 使用上檔案名稱不分大小寫

    • DateTime.cshtml 等於 datetime.cshtml
    • Decimal.cshtml 等於 decimal.cshtml

額外新增顯示格式

上述方式可以修改全站預設顯示方式,雖然方便但如果不是全站修改就不適用,以下介紹其他做法

  • 新增方式與上述做法相同

    • 在 Views –> Shared 新增 DisplayTemplates 資料夾

    1addDisplayTemplates

    • DisplayTemplates 資料夾建立 View (View 名稱不能與資料型態相同 - 會直接複寫預設格式)

    12customview

  1. 手動指定

    • 格式

      @Html.DisplayFor(modelItem => modelItem.{欄位},"{自訂 View 名稱}")
      
    • 實例

      @Html.DisplayFor(modelItem => item.ShowDateTime,"YowkoDateTime")
      
    • 自訂程式碼(YowkoDateTime.cshtml)

      @model DateTime?
      @if (Model == null)
      {
          <span class="text-danger">Yowko:No DateTime Data!!</span>
      }
      else
      {
          <span>Yowko:@(((DateTime)Model).ToString("MM/dd/yyyy HH:mm:ss"))</span>
      }
      
    • 效果

      13yowkoview

  2. 使用 UIHint attibute

    • 格式

      [UIHint("{自訂 View 名稱}")]
      public type name { get; set; }
      
    • 實例

      [UIHint("YowkoDecimal")]
      public Nullable<decimal> ShowDecimal { get; set; }
      
    • 自訂程式碼(YowkoDecimal.cshtml)

      @model decimal?
      
      @if (Model == null)
      {
          <span class="text-danger">Yowko:No Decimal Data!!</span>
      }
      else
      {
          <span>Yowko:@(((decimal)Model).ToString("N"))</span>
      }
      
    • 效果

      14yowkodecimal

    • 缺點:因為改到 .cs 需要 compile

心得

這次使用 DisplayTemplate 的過程讓我徹徹底底領悟到技術的熟悉度主要取決於使用頻率,想當年在專案公司時不用多加思考就可以搞定 DisplayTemplate,經過二、三年時間使用頻率較低現在居然記不起語法XD

有了這次經驗希望自己不要忘記實在是奢求,只求日後至少要記得可以找到自己的筆記呀 @@”

參考資訊

  1. Display templates