上手就來
新建一個模型驗證過濾器,其中ApiResp是自定義的統一響應類。
public class VldFilter:IActionFilter { /// <summary> /// 執行到action時 /// </summary> /// <param name="context"></param> public void OnActionExecuting(ActionExecutingContext context) { if (!context.ModelState.IsValid) { StringBuilder errTxt = new StringBuilder(); foreach (var item in context.ModelState.Values) { foreach (var error in item.Errors) { errTxt.Append(error.ErrorMessage + "|"); } } // api響應報文,多封裝幾個構造方法,這里使用模型驗證失敗的響應碼和模型校驗信息 ApiResp result = new ApiResp(ApiRespCode.F400000, errTxt.ToString().Substring(0, errTxt.Length - 1)); context.Result = new JsonResult(result); } } public void OnActionExecuted(ActionExecutedContext context) { } }
ApiResp大概長這樣,響應code使用自定義的枚舉,從000000到999999,有足夠的空間滿足不同類型的響應碼。
public class ApiResp { public bool Success; public string SysTime; public string Code; public string Message; public object Data; }
在startup設置Mvc options
public void ConfigureServices(IServiceCollection services) { services.AddMvc(options => { options.MaxModelValidationErrors = 5; options.Filters.Add<VldFilter>(); }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2); }
寫一個SayHello接口測試一下,然而返回數據並不是ApiResp類型,仍然是默認的返回類型。貌似並沒有執行自定義過濾器。
將Api控制器改為MVC控制器,取消[ApiController]特性,並將繼承類由ControllerBase改為Controller。
查看一下Controller與ControllerBase的差別,Controller有繼承ControllerBase和IActionFilter,ControllerBase是一個基類,沒有任何繼承類。
正確姿勢
在startup設置ApiBehaviorOptions,啟用自定義模型驗證。
public void ConfigureServices(IServiceCollection services) { services.AddMvc(options => { options.MaxModelValidationErrors = 5; options.Filters.Add<VldFilter>(); }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services.Configure<ApiBehaviorOptions>(options => { options.SuppressModelStateInvalidFilter = true; // 使用自定義模型驗證 } }
得到正確的響應類
另一種正確姿勢
直接在ApiBehaviorOptions中處理模型驗證,並封裝響應報文,不需要額外的VldFilter。但是這種方式只適用於WebApi項目,如果是MVC項目,還是使用自定義模型驗證比較好。而且WebApi項目也支持自定義模型驗證,不過需要設置ApiBehaviorOptions啟用自定義模型驗證。
public void ConfigureServices(IServiceCollection services) { services.AddMvc(options => { options.MaxModelValidationErrors = 10; //options.Filters.Add<VldFilter>(); }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2); // 實現統一模型驗證,無須VldFilter。 services.Configure<ApiBehaviorOptions>(options => {
//options.SuppressModelStateInvalidFilter = true; // 使用自定義模型驗證 options.InvalidModelStateResponseFactory = (context) => { StringBuilder errTxt = new StringBuilder(); foreach (var item in context.ModelState.Values) { foreach (var error in item.Errors) { errTxt.Append(error.ErrorMessage + "|"); } } ApiResp result = new ApiResp(ApiRespCode.F400000,errTxt.ToString().Substring(0,errTxt.Length-1)); return new JsonResult(result); }; }); }