c# - 使用通用响应模型找不到路由异常
问题描述
我试图在找不到路由时捕获异常,并使用通用响应模型包装异常。
正如问题的答案中所给出的,我尝试实施,但这个解决方案似乎也不适用于我的用例。
因为在没有找到资源时也会在响应中添加状态码 404,例如 when Id is not found
。
app.UseStatusCodePages(new StatusCodePagesOptions()
{
HandleAsync = (ctx) =>
{
if (ctx.HttpContext.Response.StatusCode == 404)
{
throw new RouteNotFoundException("Route not found");
}
return Task.FromResult(0);
}
})
RouteNotFoundException
public class RouteNotFoundException : Exception
{
public RouteNotFoundException()
: base()
{
}
public RouteNotFoundException(string message)
: base(message)
{
}
}
ApiExceptionFilterAttribute
public class ApiExceptionFilterAttribute : ExceptionFilterAttribute
{
private readonly IDictionary<Type, Action<ExceptionContext>> _exceptionHandlers;
public ApiExceptionFilterAttribute()
{
// Register known exception types and handlers.
_exceptionHandlers = new Dictionary<Type, Action<ExceptionContext>>
{
{ typeof(RouteNotFoundException), HandleNotFoundException }
};
}
public override void OnException(ExceptionContext context)
{
HandleException(context);
base.OnException(context);
}
private void HandleException(ExceptionContext context)
{
Type type = context.Exception.GetType();
if (_exceptionHandlers.ContainsKey(type))
{
_exceptionHandlers[type].Invoke(context);
return;
}
HandleUnknownException(context);
}
private void HandleNotFoundException(ExceptionContext context)
{
var exception = context.Exception as RouteNotFoundException;
var details = new ProblemDetails()
{
Type = "https://tools.ietf.org/html/rfc7231#section-6.5.4",
Title = "The specified resource was not found.",
Detail = exception.Message
};
context.Result = new NotFoundObjectResult(details);
context.ExceptionHandled = true;
}
private void HandleUnknownException(ExceptionContext context)
{
var details = new ProblemDetails
{
Status = StatusCodes.Status500InternalServerError,
Title = "An error occurred while processing your request.",
Type = "https://tools.ietf.org/html/rfc7231#section-6.6.1"
};
context.Result = new ObjectResult(details)
{
StatusCode = StatusCodes.Status500InternalServerError
};
context.ExceptionHandled = true;
}
}
ResponseWrapper 中间件
public class ResponseWrapperMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ResponseWrapperMiddleware> _logger;
public ResponseWrapperMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
{
_next = next ?? throw new ArgumentNullException(nameof(next));
_logger = loggerFactory?.CreateLogger<ResponseWrapperMiddleware>() ?? throw new ArgumentNullException(nameof(loggerFactory));
}
public async Task Invoke(HttpContext httpContext)
{
try
{
var currentBody = httpContext.Response.Body;
using (var memoryStream = new MemoryStream())
{
//set the current response to the memorystream.
httpContext.Response.Body = memoryStream;
await _next(httpContext);
//reset the body
httpContext.Response.Body = currentBody;
memoryStream.Seek(0, SeekOrigin.Begin);
var readToEnd = new StreamReader(memoryStream).ReadToEnd();
var objResult = JsonConvert.DeserializeObject(readToEnd);
var result = CommonApiResponse.Create((HttpStatusCode)httpContext.Response.StatusCode, objResult, null);
await httpContext.Response.WriteAsync(JsonConvert.SerializeObject(result));
}
}
catch (Exception ex)
{
if (httpContext.Response.HasStarted)
{
_logger.LogWarning("The response has already started, the http status code middleware will not be executed.");
throw;
}
return;
}
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class ResponseWrapperMiddlewareExtensions
{
public static IApplicationBuilder UseResponseWrapperMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<ResponseWrapperMiddleware>();
}
}
通用响应模型
public class CommonApiResponse
{
public static CommonApiResponse Create(HttpStatusCode statusCode, object result = null, string errorMessage = null)
{
return new CommonApiResponse(statusCode, result, errorMessage);
}
public string Version => "1.2.3";
public int StatusCode { get; set; }
public string RequestId { get; }
public string ErrorMessage { get; set; }
public object Result { get; set; }
protected CommonApiResponse(HttpStatusCode statusCode, object result = null, string errorMessage = null)
{
RequestId = Guid.NewGuid().ToString();
StatusCode = (int)statusCode;
Result = result;
ErrorMessage = errorMessage;
}
}
如果找不到路由并捕获通用模型中的错误,如何处理错误?这种情况的解决方法是什么?
解决方案
推荐阅读
- java - 如何更新二维数组代码中蛇和梯子的位置?
- java - 引起:io.grpc.StatusRuntimeException:内部:HTTP/2 错误代码:PROTOCOL_ERROR
- excel - MS Excel 的乘法助手 Visual Basic
- javascript - Js 类名不适用于 fetch json
- html - 尽管客户端工作 100% 正常,但在上传到主机服务器后部分网站损坏
- javascript - 从联合中删除类型或在 array.filter 中使用空联合
- python-3.x - 如何抑制或防止从 Box python API 返回的 http 标头响应在 Jupyter 笔记本的单元格输出中打印
- javascript - 如何在图表上显示不同的工具提示(在列中)?
- scala - 播放 json 的 Intellij Scala 编译问题
- java - Lombok @Builder无法解析方法'builder'