跳至頁尾內容
Iron Academy Logo
學習C#
學習C#

其他類別

在.NET 10小型API中進行資料驗證

[[academy-video-youtube({"vid": "sW_AcN-nD0Y", "start_time": "0", "title": "Data Validation in .NET 10 Minimal APIs", "creator": "Tim Corey", "length": "~10m"})]]

極簡API一直是基於控制器的ASP.NET Core的精簡替代方案,但長期以來它們有一個顯著的缺口:沒有內建的支持來驗證傳入資料。 您要麼在每個處理器內部連接手動檢查,要麼依賴第三方程式庫。 .NET 10透過提供對查詢字串、標頭和請求體的第一級資料註釋驗證來解決這個缺口,且不需要額外的套件。

根據Tim Corey的操作步驟,這篇深入探討.NET 10極簡API的文章,解釋了如何註冊驗證服務、註釋模型類並避免可能破壞您的設置的常見存取修飾符陷阱。

設置:簡單的極簡API

[0:44 - 1:35] 演示從一個基礎的ASP.NET Core極簡API專案開始,該專案運行在.NET 10上。表面範圍故意很小:兩個POST端點,每個接受不同的模型。

app.MapPost("/person", (Person person) => Results.Ok(person));
app.MapPost("/login", (LoginModel login) => Results.Ok(login));
app.MapPost("/person", (Person person) => Results.Ok(person));
app.MapPost("/login", (LoginModel login) => Results.Ok(login));

Person模型承載基本的身份字段。 LoginModel處理憑據:一個電子郵件地址、一個密碼和一個確認密碼字段。 兩者都以JSON的形式提交。 此時完全沒有輸入檢查; API接受它接收到的所有內容,包括空字串和格式錯誤的電子郵件地址。

Scalar(隨.NET 10提供的現代OpenAPI UI)用於直接從瀏覽器發送測試請求,使得在驗證接通前後可以輕鬆看到API的返回結果。

註冊驗證服務

[2:36 - 3:06] 在任何驗證屬性生效之前,您需要在服務層級進行選擇。 在服務註冊塊中進行一次調用即可啟用所有極簡API端點的執行:

builder.Services.AddValidation();
builder.Services.AddValidation();

這一行就是整個配置步驟。沒有要新增的中介軟體,沒有要掛接的流水線階段。 一旦服務註冊後,框架就會自動接管。 如果跳過此調用,您的資料註釋屬性將出現在模型上但從未被評估,請求無論包含什麼都會通過。

這是值得記住的首次除錯步驟:如果驗證無聲地不做任何事情,AddValidation() 通常是缺失的一塊。

向類模型新增驗證

[3:00 - 3:55] 註冊服務後,向基於類的模型新增驗證只是裝飾資料註釋屬性的問題:

public class Person
{
    [Required]
    public string FirstName { get; set; }

    [Required]
    public string LastName { get; set; }
}
public class Person
{
    [Required]
    public string FirstName { get; set; }

    [Required]
    public string LastName { get; set; }
}

在文件頂部新增了[Required]確保了它們被驗證。 透過Scalar發送帶有空體的POST請求現在返回400 Bad Request帶有結構化錯誤響應:

{
  "errors": {
    "FirstName": ["The FirstName field is required."],
    "LastName": ["The LastName field is required."]
  }
}

無需自定義錯誤處理,沒有過濾器屬性。 框架自動生成該響應,並且檢查在處理器體執行之前運行,因此您永遠不需要在端點邏輯內檢查空值。

將驗證應用於紀錄

[4:29 - 5:30] 相同的屬性適用於C#紀錄,但語法略有不同,因為紀錄屬性通常定義在主構造函式中,而不是作為單獨的成員聲明。

public record LoginModel(
    [Required] [EmailAddress] string Email,
    [Required] string Password,
    [Required] string ConfirmPassword
);
public record LoginModel(
    [Required] [EmailAddress] string Email,
    [Required] string Password,
    [Required] string ConfirmPassword
);

構造函式參數上的屬性應用於生成的屬性,因此[EmailAddress]的行為與類上的完全相同。 發送格式錯誤的電子郵件請求,比如Email字段無效。

Password匹配。 在紀錄中,屬性目標需要明確的提示,因為編譯器必須知道您指的是生成的成員,而不是構造函式參數本身:

[property: Compare(nameof(Password))]
string ConfirmPassword
[property: Compare(nameof(Password))]
string ConfirmPassword

[property:]目標告訴編譯器將屬性附加到生成的成員而不是參數。 沒有它,[Compare]編譯但無法在檢查期間執行。 這是在此上下文中使用紀錄與類最棘手的部分:類屬性自然接受屬性,而紀錄參數需要對成員層級運行的任何操作的明確目標。

公共存取修飾符要求

[7:51 - 9:00] 一個常見的陷阱很容易被忽略,當您碰到它時不會產生錯誤訊息。 驗證系統使用反射在運行時檢查您的模型型別;為了讓反射找到型別的成員,型別本身必須標記為public

// Validation will NOT run; the class is internal by default
class Person { ... }

// Validation runs correctly
public class Person { ... }
// Validation will NOT run; the class is internal by default
class Person { ... }

// Validation runs correctly
public class Person { ... }

同樣的規則適用於紀錄。 如果您的模型未聲明存取修飾符,C#預設為internal,服務完全跳過它。 您的端點仍然接收請求,處理器仍然執行,且不返回錯誤; 檢查只是不作任何動作。

這是ASP.NET Core的行為,不專屬於極簡API,但它在這裡更常發生,因為這些專案往往很緊緻,開發人員有時在線內或與Program.cs在相同文件中定義模型,而沒有考慮可見性。

快速審核專案的方法:任何傳遞到端點處理程式的模型型別都應明確標記為public。 如果不是,無論多少屬性都無法讓框架運行。

您可以驗證什麼

內建的資料註釋屬性涵蓋了最常見的場景,無需任何額外工作:

  • [Required]拒絕空或空值
  • [EmailAddress]驗證電子郵件字串的格式
  • [Compare]檢查兩個屬性是否匹配,這對密碼確認很實用
  • [Range]執行數字或日期界限
  • [StringLength]用可選的最小值限制字串長度
  • [RegularExpression]對照自定義模式驗證

這些都可用於查詢字串參數、請求標頭和JSON主體。 同一個模型類或紀錄可以從不同來源綁定,而無需更改其任何屬性。

結論

[7:46 - end] 註冊AddValidation()後,並且模型增加了裝飾後,極簡API自動針對類別和紀錄強制執行輸入約束。要在.NET 10中實現此功能,只需調用public

紀錄上的public修飾符要求是唯一真正的難點。 它們很容易被忽視并產生無聲故障而非編譯錯誤,因此每當輸入檢查顯示無效時,將它們放到您的檢查清單中。

觀看Tim Corey的YouTube影片上的頻道以獲取完整的源程式碼操作步驟。

Hero Worlddot related to 在.NET 10小型API中進行資料驗證
Hero Affiliate related to 在.NET 10小型API中進行資料驗證

分享您所愛以賺取更多報酬

您是否為使用 .NET、C#、Java、Python 或 Node.js 的開發者建立內容?將您的專業知識轉化為額外收入!

Iron 支援團隊

我們線上24小時,每週5天。
聊天
電子郵件
給我打電話