我使用了很多asp.net核心筛选器。
我正在寻找一种优雅的方法来处理过滤器可能引发的异常。
例如这样的过滤器:
public async void OnAuthorization(AuthorizationFilterContext context){
Convert.ToInt32("NotConvertable");
}
将抛出FormatException,这将使整个应用程序崩溃,这不是很酷。我想记录错误,返回500但没有应用程序崩溃。
我尝试在MVC之前添加中间件:
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError("FATAL ERROR", ex);
}
但这仍然无济于事。
我正在考虑使try {}赶上500,并在每个过滤器中进行某种日志记录,但这会导致大量重复。
有什么办法可以全局处理吗?
更多背景
public class PermissionAttribute:TypeFilterAttribute
{
public PermissionAttribute():base(typeof(PermissionFilter))
{
}
}
public class PermissionFilter : IAuthorizationFilter
{
public async void OnAuthorization(AuthorizationFilterContext context)
{
Convert.ToInt32("NotConvertable");
}
}
和控制器:
[Route("api/nav/")]
public class AController : Controller{
...
[HttpGet]
[Route("{id}")]
[PermissionAttribute]
[ProducesResponseType(typeof(SomeClass), 200)]
public async Task<SomeClass> GetAll()
{
...
}
}
将此端点称为粉碎整个过程
Startup.cs(简称)public void Configure(...某些服务){
... some app.Use UseLogger, HealthCheck
app.UseMiddleware<PleaseDontCrushMiddleware>(); // Middleware mentioned above
app.UseExceptionHandler(errorHandler.Handle);
a lot of middlewares
app.UseMvc(RouteTable);
}
MVC服务是通过以下方式添加的:
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
config.Filters.Add(new ResponseCacheFilter(new CacheProfile()
{
NoStore = true,
Location = ResponseCacheLocation.None
},
services.BuildServiceProvider().GetService<ILoggerFactory()));
}
假设您将在某些方法中引发某些特定的异常,而其他方法仅想作为System.Exception捕获,则可以使用以下方法:
您可以创建异常处理扩展方法(如果您也想使用Logger,也可以在方法中添加ILogger参数并从Startup.Configure传递它):
public static class ExceptionHandler
{
/// <summary>
///
/// </summary>
/// <param name="app"></param>
public static void UseCustomExceptionHandler(this IApplicationBuilder app)
{
app.UseExceptionHandler(eApp =>
{
eApp.Run(async context =>
{
context.Response.StatusCode = 500;
context.Response.ContentType = "application/json";
var errorCtx = context.Features.Get<IExceptionHandlerFeature>();
if (errorCtx != null)
{
var ex = errorCtx.Error;
var message = "Unspecified error ocurred.";
var traceId = traceIdentifierService.TraceId;
if (ex is ValidationException)
{
var validationException = ex as ValidationException;
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
message = string.Join(" | ", validationException.Errors.Select(v => string.Join(",", v.Value)));
}
else if (ex is SomeCustomException)
{
var someCustomException = ex as SomeCustomException;
...
}
var jsonResponse = JsonConvert.SerializeObject(new ErrorResponse
{
TraceId = traceId,
Message = message
});
await context.Response.WriteAsync(jsonResponse, Encoding.UTF8);
}
});
});
}
}
然后您只需在启动配置中注册它:
public void Configure(IApplicationBuilder app)
{
...
app.UseCustomExceptionHandler();
...
}
关于授权筛选器中的异常(来自Microsoft文档):
不要在授权过滤器中引发异常:
The exception will not be handled. Exception filters will not handle the exception.
考虑在授权过滤器中发生异常时发出挑战
您可以在此处了解更多信息:https : //docs.microsoft.com/zh-cn/aspnet/core/mvc/controllers/filters?view=aspnetcore-3.1#action-filters
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句