在開發表單型系統的時候,尤其是專案初期,表單的格式一直在改變,有時候增加欄位,有時候又要修改欄位,而在前後端分離的架構下,每改一次前後端的資料模型就要跟著動一次,改到最後其實有點煩躁,於是開始思考能否用 dynamic
型別來接收這一直還沒確定下來的資料模型物件,於是出現了這篇方法。
這作法只是為了在專案變動性很大的時候,加速專案開發,一般還是建議基於有規範的資料模型往下開發,對之後的維護比較有幫助。
要實現用 dynamic
型別來接收傳進來的資料,其實動作很簡單,只是有一個小問題要先處理,就是在 ASP.NET Core 3.x 以後的專案都是使用 System.Text.Json
來處理 JSON 資料繫結,而這會讓後面處理變得比較不漂亮,因此請先參考這篇在 ASP.NET Core 專案中改用 JSON.NET 做資料繫結文章,改用 JSON.NET 做資料繫結才會比較漂亮。
處理完上面的問題後,我新增了一個 FormController
及一個 Data
Action,這裡我使用 [FromRoute]
來取得表單類型,然後從 [FromBody]
取得該表單的詳細資料並用 dynamic
型別來接,裡面再搭配 C# 8 的 Switch 寫法來分別轉到特定表單的處理細節,程式碼其實非常簡單:
// POST /form/{type}/
[HttpPost]
[Route("{type}")]
public IActionResult Data([FromRoute] string type, [FromBody] dynamic query)
{
return type switch
{
"AForm" => Ok($"{(string)query.Title} - {(string)query.Description}"),
"BForm" => Ok($"{(string)query.Name} {(int)query.Number}"),
_ => Ok("Not support this form."),
};
}
如果沒有改用 JSON.NET 做資料繫結,那這裡執行時就會出現
RuntimeBinderException: 'System.Text.Json.JsonElement' does not contain a definition for 'XXX'
例外訊息。
這裡要注意的是,因為 dynamic
是執行時期判斷資料型別,因此為避免資料型別錯亂,在每一次使用 dynamic
資料變數的時候,建議都手動強制轉型,避免後續處理發生錯誤。
呼叫結果如下:
當然,這邊只是簡單展示一下想要表達的概念,後續其實還有很多要藉接商業邏輯的動作,這裡就不多敘述了。
本篇完整範例程式碼請參考 poychang/Demo-DynamicDataModelWebAPI。
參考資料: