官方建議用app.UseExceptionHandler("/error")來(lái)集中處理異常,本例是一個(gè)具體的應(yīng)用。
比如項(xiàng)目中有一個(gè)ViewModel,要求Name最大長(zhǎng)度為5
/// <summary>/// 用戶(hù)模型/// </summary>public class UserModel{/// <summary>/// ID/// </summary>public int ID { get; set; }/// <summary>///名稱(chēng)///?</summary>??[MaxLength(5, ErrorMessage = "長(zhǎng)度不能超過(guò)5")]public string Name { get; set; }}
在TestController中有兩個(gè)Action,都有異常的機(jī)率,Get方法中,一個(gè)異常是系統(tǒng)內(nèi)置的0被整除,另一個(gè)是我們自定義的業(yè)務(wù)層級(jí)異常(.NET架構(gòu)小技巧(8)中有涉及);AddUser是有Model驗(yàn)證有可能Name超過(guò)5個(gè)字符后報(bào)異常。Error方法一個(gè)錯(cuò)誤處理Action,根據(jù)上下文的異常來(lái)分流系統(tǒng)內(nèi)置異常,還是自定業(yè)務(wù)異常。
????????///?<summary>/// get接口/// </summary>/// <returns></returns>[HttpGet]public IActionResult Get(){var ran = new Random();switch (ran.Next(1, 4)){case 1:int i = 0;var j = 10 / i;return Ok();case 2:throw new RegisteredException("這是一個(gè)錯(cuò)誤");default:return Ok();}}/// <summary>///?添加用戶(hù)接口/// </summary>/// <param name="user"></param>/// <returns></returns>[HttpPost("/adduser")]public IActionResult AddUser([FromBody] UserModel user){return Ok(user);}///?<summary>/// 錯(cuò)誤處理頁(yè)/// </summary> /// <returns></returns>[HttpGet("/error")]public IActionResult Error(){var context = HttpContext.Features.Get<IExceptionHandlerFeature>();//如果是業(yè)務(wù)自定義異常,進(jìn)行特殊處理if (context.Error is DaMeiException){return Problem(detail: context.Error.StackTrace, title: $"{context.Error.Message}", type: "HIS");}else{return Problem(detail: context.Error.StackTrace, title: context.Error.Message);}}
層級(jí)異常類(lèi)
using?System;
namespace WebApiError
{/// <summary>/// 產(chǎn)品異常/// </summary>public class DaMeiException : ApplicationException{/// <summary>/// /// </summary>/// <param name="message"></param>public DaMeiException(string message) : base(message){}}/// <summary>/// His項(xiàng)目異常/// </summary>public class HisException : DaMeiException{/// <summary>/// /// </summary>/// <param name="message"></param>public HisException(string message) : base(message){}}/// <summary>/// Lis項(xiàng)目異常/// </summary>public class LisException : DaMeiException{/// <summary>/// /// </summary>/// <param name="message"></param>public LisException(string message) : base(message){}}/// <summary>/// 模塊異常/// </summary>public class RegisteredException : HisException{/// <summary>/// /// </summary>/// <param name="message"></param>public RegisteredException(string message) : base(message){}}
}
Error的Action之所有調(diào)用到,是因?yàn)镃onfigure中添加如下代碼,把所有異常交給"/error"來(lái)處理。
app.UseExceptionHandler("/error");
添加DaMeiProblemDetailsFactory來(lái)兼容各類(lèi)異常,自定義異常和Model驗(yàn)證異常
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using System.Collections.Generic;namespace WebApiError
{///?<summary>/// /// </summary>public class DaMeiProblemDetailsFactory : ProblemDetailsFactory{/// <summary>///?處理業(yè)務(wù)錯(cuò)誤/// </summary>/// <param name="httpContext"></param>/// <param name="statusCode"></param>/// <param name="title"></param>/// <param name="type"></param>/// <param name="detail"></param>/// <param name="instance"></param>/// <returns></returns>public override ProblemDetails CreateProblemDetails(HttpContext httpContext, int? statusCode = null, string title = null, string type = null, string detail = null, string instance = null){var problem = new ProblemDetails(){Title = string.IsNullOrEmpty(type) ? title : $"業(yè)務(wù)異常錯(cuò)誤:{title}",Detail = detail,Status = statusCode,Instance = instance,Type?=?type};return problem;}/// <summary>/// 處理model驗(yàn)證錯(cuò)誤/// </summary>/// <param name="httpContext"></param>/// <param name="modelStateDictionary"></param>/// <param name="statusCode"></param>/// <param name="title"></param>/// <param name="type"></param>/// <param name="detail"></param>/// <param name="instance"></param>/// <returns></returns>public override ValidationProblemDetails CreateValidationProblemDetails(HttpContext httpContext, ModelStateDictionary modelStateDictionary, int? statusCode = null, string title = null, string type = null, string detail = null, string instance = null){var problem = new ValidationProblemDetails(){Title = "Model驗(yàn)證錯(cuò)誤",Detail = detail,Status = statusCode,Instance = instance,Type = type};foreach (var a in modelStateDictionary){var errorList = new List<string>();foreach (var error in a.Value.Errors){errorList.Add(error.ErrorMessage);}problem.Errors.Add(new KeyValuePair<string, string[]>(a.Key, errorList.ToArray()));}return problem;}}
}
在ConfigureServices中需要注入DaMeiProblemDetailsFactory
services.AddTransient<ProblemDetailsFactory, DaMeiProblemDetailsFactory>();
其實(shí)還可以用Action過(guò)濾器來(lái)統(tǒng)一管理異常
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;namespace WebApiError
{/// <summary>/// 自定義過(guò)濾器處理異常/// </summary>public class DaMeiExceptionFilter : IActionFilter, IOrderedFilter{/// <summary>/// /// </summary>public int Order { get; } = int.MaxValue - 10;/// <summary>/// /// </summary>/// <param name="context"></param>public void OnActionExecuting(ActionExecutingContext context) { }/// <summary>/// /// </summary>/// <param name="context"></param>public void OnActionExecuted(ActionExecutedContext context){if (context?.Exception != null){context.Result = new ObjectResult(context.Exception.Message){StatusCode = 500};context.ExceptionHandled = true;} }}
}
另外一種方式是通過(guò)Action過(guò)濾器來(lái)處理
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;namespace WebApiError
{/// <summary>/// 自定義過(guò)濾器處理異常/// </summary>public class DaMeiExceptionFilter : IActionFilter, IOrderedFilter{/// <summary>/// /// </summary>public int Order { get; } = int.MaxValue - 10;/// <summary>/// /// </summary>/// <param name="context"></param>public void OnActionExecuting(ActionExecutingContext context){}/// <summary>/// /// </summary>/// <param name="context"></param>public void OnActionExecuted(ActionExecutedContext context){if (context?.Exception != null){if (context.Exception is DaMeiException){context.Result = new ObjectResult(context.Exception.Message){Value = $"業(yè)務(wù)異常:{ context.Exception.Message}",StatusCode = 500};}else{context.Result = new ObjectResult(context.Exception.Message){Value = context.Exception.Message,StatusCode = 500};}context.ExceptionHandled = true;}}}
}
添加全局過(guò)濾器
services.AddControllers(options =>
{options.Filters.Add(new?DaMeiExceptionFilter());
});
總結(jié)
以上是生活随笔為你收集整理的asp.net core web api之异常的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。