首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

ASP.NET MVC Model 驗證系統運作機制:從 ModelState 到驗證執行流程

     編輯:關於ASP.NET

ModelState:驗證結果的容器

Controller.ViewData.ModelState 為 ModelStateDictionary,鍵為欄位名稱(含前綴),值為 ModelState:

[Serializable]
public class ModelState
{
    public ModelErrorCollection Errors { get; } // 驗證錯誤集合
    public ValueProviderResult Value { get; set; } // 繫結原始值
}

[Serializable]
public class ModelErrorCollection : Collection<ModelError>
{
    public void Add(Exception exception);
    public void Add(string errorMessage);
}

[Serializable]
public class ModelError
{
    public ModelError(Exception exception);
    public ModelError(string errorMessage);
    public ModelError(Exception exception, string errorMessage);
    public string ErrorMessage { get; }
    public Exception Exception { get; }
}

驗證在 Model 繫結管線中的位置

Model 驗證發生於 Model 繫結之後、Action 執行之前。DefaultModelBinder 為每個屬性繫結值後,立即呼叫對應 ModelValidator 執行驗證,失敗則將 ModelError 加入 ModelState。

實驗驗證:AlwaysFailsAttribute 自動產生 ModelError

定義永遠失效的驗證屬性:

public class AlwaysFailsAttribute : ValidationAttribute
{
    public override bool IsValid(object value) => false;
}

套用至巢狀 Model:

[AlwaysFails(ErrorMessage = "Contact")]
public class Contact
{
    [AlwaysFails(ErrorMessage = "Contact.Name")] public string Name { get; set; }
    [AlwaysFails(ErrorMessage = "Contact.PhoneNo")] public string PhoneNo { get; set; }
    [AlwaysFails(ErrorMessage = "Contact.EmailAddress")] public string EmailAddress { get; set; }
    [AlwaysFails(ErrorMessage = "Contact.Address")] public Address Address { get; set; }
}

[AlwaysFails(ErrorMessage = "Address")]
public class Address
{
    [AlwaysFails(ErrorMessage = "Address.Province")] public string Province { get; set; }
    [AlwaysFails(ErrorMessage = "Address.City")] public string City { get; set; }
    [AlwaysFails(ErrorMessage = "Address.District")] public string District { get; set; }
    [AlwaysFails(ErrorMessage = "Address.Street")] public string Street { get; set; }
}

提交表單後,ModelState 將包含所有層級的錯誤:

  • 頂層:Contact 錯誤
  • 純量屬性:Contact.Name、Contact.PhoneNo、Contact.EmailAddress
  • 複雜屬性:Contact.Address 錯誤
  • 巢狀屬性:Contact.Address.Province、City、District、Street

驗證執行核心流程

  1. ControllerActionInvoker 呼叫 GetParameterValue 繫結參數。
  2. DefaultModelBinder.BindModel 遞迴繫結屬性。
  3. 每屬性繫結完成,呼叫 OnModelUpdated → Validate。
  4. Validate 透過 ModelValidatorProviders.Providers.GetValidators(metadata, context) 取得所有 ModelValidator。
  5. 逐一呼叫 validator.Validate(container)。
  6. 收集 ModelValidationResult,轉為 ModelError 加入 bindingContext.ModelState。

遞迴驗證與 MemberName

  • 頂層物件驗證:ModelValidationResult.MemberName = String.Empty。
  • 屬性驗證:MemberName = 屬性名稱(含前綴,如 Address.Province)。
  • 巢狀物件屬性:完整路徑作為 Key 存入 ModelStateDictionary。

驗證結果存取

Action 內可透過 ModelState.IsValid 判斷整體驗證結果,ModelState["Key"].Errors 取得特定欄位錯誤訊息。View 中 Html.ValidationMessageFor、Html.ValidationSummary 自動讀取顯示。

總結

MVC 驗證系統以 ModelValidator 為核心,整合於 Model 繫結遞迴流程中,結果統一存入 ModelStateDictionary。理解此流程有助於自訂繫結器、驗證屬性或錯誤處理邏輯。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved