ASP.NET Core Exception middelware 每层嵌套异常
ASP.NET Core Exception middelware nesting exceptions for each layer
我创建了一个全局异常处理程序中间件来捕获我所有的自定义异常。
在我的 DAL 中抛出异常时,我希望中间件能够将其捕获为与抛出的类型相同的异常。
// API
[HttpGet]
[Route("api/users")]
public IActionResult Get(int id)
{
var user = _userService.GetById(id);
return Ok(user);
}
// Repository
public async Task<List<User>> GetById(int id)
{
throw new EntityNotFoundException("code", "message");
// .. return user
}
// Exception handler
public async Task Invoke(HttpContext httpContext)
{
try
{
await _next(httpContext);
}
catch (Exception ex) // ex is of type JsonSerializationException
{
if (ex is EntityNotFoundException)
{
// Handle exception
}
}
}
在上面的示例中,异常已被处理,但属于 JsonSerializationException 类型,其中包含类型为 System.AggregateException 的 InnerException,后者包含另一个类型为 EntityNotFoundException 的 InnerException。
似乎异常嵌套在它传递的每一层中(DAL > 服务 > API)。我怎样才能避免这种情况,以便我可以将异常捕获为原始类型?
you provided looks good but it lacks one important thing, which is single responsibility.
ASP.NET Core 有一个更好的方法,它使用 exception filters,它也可以全局注册并且可以为每个 custom-exception 甚至未处理的异常编写。
样本:
public class EntityNotFoundExceptionFilter : IExceptionFilter
{
public EntityNotFoundExceptionFilter(// some dependencies that u want to inject)
{
...
}
public void OnException(ExceptionContext context)
{
if (!(context.Exception is EntityNotFoundException))
{
return;
}
context.ExceptionHandled = true;
context.Result = new NotFoundObjectResult // will produce 404 response, you can also set context.HttpContext.Response.StatusCode based on your exceptions statuscode and return an ObjectResult instead
{
context.Exception.Message
}
}
}
现在在你的Startup.cs中的ConfigureServices(...)
函数中添加下面的
public void ConfigureService(IServiceCollection services)
{
...
services.AddMvc(options =>
{
...
options.Filters.Add(typeof(EntityNotFoundExceptionFilter));
...
}
...
}
你最终会写很多过滤器,但这是一种更简洁的方法,这就是应该使用 asp.net-core filterpipeline 的方式 + 这将起作用:)
我不是 100% 确定为什么在您当前的实现中有这么多异常,但我的猜测是 asp.net 尝试 return 异常然后无法序列化它和类似的东西.
编辑:
我创建了一个最小示例,可以在克隆项目后找到 here. Just access the url via http://localhost:58741/api/some。
我创建了一个全局异常处理程序中间件来捕获我所有的自定义异常。
在我的 DAL 中抛出异常时,我希望中间件能够将其捕获为与抛出的类型相同的异常。
// API
[HttpGet]
[Route("api/users")]
public IActionResult Get(int id)
{
var user = _userService.GetById(id);
return Ok(user);
}
// Repository
public async Task<List<User>> GetById(int id)
{
throw new EntityNotFoundException("code", "message");
// .. return user
}
// Exception handler
public async Task Invoke(HttpContext httpContext)
{
try
{
await _next(httpContext);
}
catch (Exception ex) // ex is of type JsonSerializationException
{
if (ex is EntityNotFoundException)
{
// Handle exception
}
}
}
在上面的示例中,异常已被处理,但属于 JsonSerializationException 类型,其中包含类型为 System.AggregateException 的 InnerException,后者包含另一个类型为 EntityNotFoundException 的 InnerException。
似乎异常嵌套在它传递的每一层中(DAL > 服务 > API)。我怎样才能避免这种情况,以便我可以将异常捕获为原始类型?
ASP.NET Core 有一个更好的方法,它使用 exception filters,它也可以全局注册并且可以为每个 custom-exception 甚至未处理的异常编写。
样本:
public class EntityNotFoundExceptionFilter : IExceptionFilter
{
public EntityNotFoundExceptionFilter(// some dependencies that u want to inject)
{
...
}
public void OnException(ExceptionContext context)
{
if (!(context.Exception is EntityNotFoundException))
{
return;
}
context.ExceptionHandled = true;
context.Result = new NotFoundObjectResult // will produce 404 response, you can also set context.HttpContext.Response.StatusCode based on your exceptions statuscode and return an ObjectResult instead
{
context.Exception.Message
}
}
}
现在在你的Startup.cs中的ConfigureServices(...)
函数中添加下面的
public void ConfigureService(IServiceCollection services)
{
...
services.AddMvc(options =>
{
...
options.Filters.Add(typeof(EntityNotFoundExceptionFilter));
...
}
...
}
你最终会写很多过滤器,但这是一种更简洁的方法,这就是应该使用 asp.net-core filterpipeline 的方式 + 这将起作用:)
我不是 100% 确定为什么在您当前的实现中有这么多异常,但我的猜测是 asp.net 尝试 return 异常然后无法序列化它和类似的东西.
编辑:
我创建了一个最小示例,可以在克隆项目后找到 here. Just access the url via http://localhost:58741/api/some。