iT邦幫忙

2024 iThome 鐵人賽

DAY 20
0

前言

今天要分享一個從 .NET Framework 開始,就有的應用 : Model Binding ,相信這主題大家都知道了,但它很常見,也會用到,所以也必須納入這系列之一,也請耐心看完 /images/emoticon/emoticon33.gif

分享主軸

  • 繫結是什麼 ?
  • 繫結種類
  • 繫結驗證

Model Binding

簡單來說就是將 HTTP 請求資料(如 : 表單數據、路由數據、查詢字符串和標頭 )綁定到對應方法的參數上

  • 減少了手動解析和轉換原始 HTTP 請求數據的需求
  • 讓開發者專心在邏輯上
  • 如果繫結發生失敗,預設回傳 400 ( BadRequest )

來源

  1. 表單(Form Values):來自 HTTP POST 請求的表單資料
  2. 路由(Route Values):在 URL 模板中定義的路由參數
  3. 查詢字符串(Query Strings):URL 中的查詢參數
  4. 請求正文(Request Body):通常用於 JSON 或 XML 格式的資料
  5. HTTP 標頭(HTTP Headers):來自 HTTP 請求標頭的資料

來源屬性

  • [FromQuery]

用來比對 比對 Query String 上面的值,如果是簡單類型(如 int、string 等),會自動繫結,不需要特別標註 [FromQuery],除了複雜模型 (如自定義類別),就得使用它來指定,如下範例

  1. 簡單型別
        [HttpGet]
        public IActionResult Get(int number)
        {
            return Ok(number);
        }

Request出去的網址如下

https://localhost:7161/WeatherForecast/Get?number=123
  1. 使用複雜型別沒放 FromQuery 屬性,會發生錯誤
TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body

正確使用

        [HttpGet]
        public IActionResult Get([FromQuery] Pet pet)
        {
            // pet 會從查詢字符串中繫結
            return Ok(pet);
        }

Request出去的網址如下
https://ithelp.ithome.com.tw/upload/images/20241003/20133954a6oBqCR6Kd.png

  • [FromBody]

  1. 如果套用 ApiController,預設就會套用複雜模型,從 Request Body 取值
  2. 當簡單模型中內容過大,這時候也可以使用它來繫結
  3. 當 [FromBody] 屬性應用於複雜類型參數時,該參數的所有其他繫結源屬性(如 [FromQuery])將被忽略,每個 API 方法,只能被宣告一個此屬性

不管有沒有加此屬性,都會正常繫結到(所以如果專案上有寫這屬性,可能要檢查一下是否有多餘的寫法)

        [HttpPost]
        public IActionResult Post(Pet pet)
        {
            return Ok(pet);
        }
  • [FromHeader]

  • 從 HTTP 標頭中提取值並將其繫結到控制器方法的參數上

  • 只會從 HTTP Request 取值

  • 只能套用簡單模型

簡單模型

    [HttpGet("header")]
    public IActionResult GetHeaderValue([FromHeader(Name = "X-Custom-Header")] string customHeader)
    {
        return Ok(new { HeaderValue = customHeader });
    }

結果
https://ithelp.ithome.com.tw/upload/images/20241003/20133954UAv7bc6Coy.png

其他屬性如
[FromServices] : 可以在某個 action 用這屬性去注入任何的一個服務
[FromForm]
[FromRoute]

模型驗證

using System.ComponentModel.DataAnnotations;

...
{
    public class UserModel
    {
        [Required(ErrorMessage = "Name is required")]
        [StringLength(50, MinimumLength = 2, ErrorMessage = "Name must be between 2 and 50 characters")]
        public string Name { get; set; } = null!;

        [Required(ErrorMessage = "Email 必填")]
        [EmailAddress(ErrorMessage = "Email Address 格式不正確")]
        public string Email { get; set; } = null!;

        [Required(ErrorMessage = "Age 必填")]
        [Range(18, 30, ErrorMessage = "Age 必須介於 18 ~ 30")]
        public int Age { get; set; }

        [Phone(ErrorMessage = "電話格式不正確")]
        public string? PhoneNumber { get; set; }
    }
}

範例
https://ithelp.ithome.com.tw/upload/images/20241003/201339543KMn0Pqu0R.png

自訂模型繫結
https://learn.microsoft.com/zh-tw/aspnet/core/mvc/advanced/custom-model-binding?view=aspnetcore-8.0#recommendations-and-best-practices

今日結語

終於堅持到這系列的 2/3 文章了!!! 特別安排一個比較簡單的主題放在第 20 天 /images/emoticon/emoticon01.gif

雖然今日主題,一定是大家都耳熟能想的知識了,但它也是專案上常常使用到的,透過這主題再次複習到一些基本觀念!

明天繼續努力,謝謝 ~

參考文章
https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-8.0


上一篇
Day 19 Routing : ASP.NET Core 中的導航
下一篇
Day 21 Views : 特性與使用技巧
系列文
靠近 ASP .NET Core 一點點27
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言