開發 API 常會透過 ValidationAttribute 來規範 Request Model 屬性的特殊要求,預設當這些 Model 檢核不過時會以 HTTP Status 400 狀態回應,此時若團隊已有規範通用性的回應結構來傳遞所有訊息狀態時,就必須捨棄原本機制並自行定義所需的 Invalid Model State 回應方式。
前言
開發 API 常會透過 ValidationAttribute 來規範 Request Model 屬性的特殊要求,例如常見標籤 [Required], [MaxLength(max)], [RegularExpress(reg)] 分別表示必填、限制最大長度及使用正則表示式規範傳入字串的格式,預設當這些 Model 檢核不過時會以 HTTP Status 400 狀態回應,此時若團隊已有規範通用性的回應結構來傳遞所有訊息狀態時,就必須捨棄原本機制並自行定義所需的 Invalid Model State 回應方式。以下介紹。
使用版本
ASP.NET Core 2.1
停用 ModelStateInvalidFilter
系統預設是透過 ModelStateInvalidFilter 來篩出 Model 驗證失敗的 Request 作錯誤回應,將該錯誤資訊收集後以 HTTP Status 400 連同錯誤資訊回應給呼叫端;因此我們可以透過 SuppressModelStateInvalidFilter = true 設定來停止這個 Filter 發生作用,成功設定後當 Model 驗證失敗則不會有錯誤回應。
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// 停止 Invalid ModelState Filter (關閉後 Model 驗證失敗會無反應)
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
}
// 略 ...
}
建立自訂 ValidateModelFilter
由於預設的 Model 驗證錯誤處理機制已被關閉,因此當 Model 驗證發生錯誤時,我們就必須自行建立一個 Action Filter 來介入處理 Model 驗證失敗時的處置方式;以下列代碼為例,若團隊已經有制定通用性的 Respose 物件時,可以在錯誤發生時仍以 HTTP Status 200 正常回應,並透過此通用性物件來呈現錯誤資訊。
public class ValidateModelFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
// 取得 Model 錯誤資訊
var modesState = context.ModelState;
var errors = modesState.Keys
.SelectMany(key => modesState[key].Errors.Select(x => new { key, msg = x.ErrorMessage }))
.ToList();
// 產生專案規範通用回應格式
var result = new
{
header = new
{
isSuccess = false,
code = "E0001",
message = "Model Invalid"
},
body = new
{
errors
}
};
// 回應結果
context.Result = new JsonResult(result);
}
}
// 略 ...
}
全域註冊 ValidateModelFilter
最後直接將剛才建立的 ValidateModelFilter 加入系統流程中就搞定了,請參考以下代碼。
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// 略 ...
// 加入自訂 Validate Model Filter 執行 Model 驗證失敗的處置
services
.AddMvc(options =>
{
options.Filters.Add(typeof(ValidateModelFilter));
/* other filters ... */
});
}
}
執行結果
假設登入系統 API 的 Request Body Model 定義如下,標示 [Required] 表示 Pcode 與 UserId 都是必填資訊。
當未填寫 UserId 與 Pcode 情境下送至 API 端時,會在 Model 繫結驗證時判定不合法,並在通過我們所定義的 ValidateModelFilter 被濾出,以我們所預期的通用性結構回應呼叫端,以下為測試時所呈現的結果,這樣就達到我們所預期的效果了。
希望此篇文章可以幫助到需要的人
若內容有誤或有其他建議請不吝留言給筆者喔 !