跳過到頁腳內容
Iron Academy Logo
學習 C#
學習 C#

其他分類

.NET 10 簡約 API 中的資料驗證

Tim Corey
~10m

Minimal API 一直是基於控制器的ASP.NET Core的精簡替代方案,但長期以來有一個顯著的缺口:沒有內建的支援來驗證傳入資料。 您可以在每個處理程式中連線上手動檢查,或者依靠第三方程式庫。 .NET 10 填補了這個缺口,為查詢字串、標頭和請求主體提供了第一級的資料註釋驗證,所有這些都不需要額外的套件。

這次深入探討.NET 10 Minimal API,基於Tim Corey的通過,解釋了如何註冊驗證服務、註釋模型類別,以及避免常見的訪問修飾符陷阱,這些陷阱可能會破壞您的設置。

設置:一個簡單的Minimal API

[0:44 - 1:35] 演示從一個基本的ASP.NET Core Minimal 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] 在任何驗證屬性生效之前,您需要在服務級別選擇加入。 在您的服務註冊塊中調用一次即可在所有 Minimal 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."]
  }
}

無需自定義錯誤處理,無需過濾屬性。 框架自動產生該響應,並且檢查在您的處理程式主體執行之前運行,因此您永遠不需要在端點邏輯內防範null。

將驗證應用於記錄

[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的行為,而不是Minimal API特有的,但它在這裡更常見,因為這些專案傾向於緊湊,開發者有時會在線定義模型或在與Program.cs相同的文件中定義,而不考慮可見性。

審核專案的一種快捷方式:任何傳入端點處理程式的模型類型應明確標記為public。 如果不是,無數的屬性都無法使框架生效。

您可以驗證的內容

內建的資料註釋屬性涵蓋了最常見的情況,無需額外工作:

  • [Required] 拒絕null或空值
  • [EmailAddress] 驗證電子郵件字符串的格式
  • [Compare] 檢查兩個屬性是否匹配,有助於密碼確認
  • [Range] 強制執行數字或日期邊界
  • [StringLength] 以可選的最小值為字符串長度設置上限
  • [RegularExpression] 與自定義模式驗證

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

結論

[7:46 - end] 註冊AddValidation()並裝飾您的模型後,Minimal 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的開發者創建內容?將您的專業知識轉化為額外收入!

鋼鐵支援團隊

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