C# WebAPI筛选器的ActionExecuteContext中的异常属性为null
我已经使用同一个异常过滤器好几个月了,到目前为止,它的性能非常好。这是:C# WebAPI筛选器的ActionExecuteContext中的异常属性为null,c#,exception,asp.net-core-3.0,C#,Exception,Asp.net Core 3.0,我已经使用同一个异常过滤器好几个月了,到目前为止,它的性能非常好。这是: public class HttpResponseExceptionFilter : IActionFilter, IOrderedFilter { public int Order { get; set; } = int.MaxValue - 10; public void OnActionExecuting(ActionExecutingContext context) { }
public class HttpResponseExceptionFilter : IActionFilter, IOrderedFilter
{
public int Order { get; set; } = int.MaxValue - 10;
public void OnActionExecuting(ActionExecutingContext context)
{
}
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Exception is HttpResponseException exception)
{
context.Result = new ObjectResult(new {Mensagem = context.Exception.Message})
{
StatusCode = exception.Status,
};
context.ExceptionHandled = true;
}
else if (context.Exception is Exception)
{
var message = context.Exception.InnerException != null ? context.Exception.InnerException.Message : context.Exception.Message;
context.Result = new ObjectResult(new RetornoExceptionApi(message))
{
StatusCode = StatusCodes.Status500InternalServerError
};
context.ExceptionHandled = true;
}
}
}
简单明了。我一直在使用它来捕获自定义HTTP异常,其中HttpResponseException是基类。这就是它看起来的样子:
public class HttpResponseException : Exception
{
public int Status { get; set; } = StatusCodes.Status500InternalServerError;
public HttpResponseException(int statusCode)
{
Status = statusCode;
}
}
没什么。这是404状态代码的自定义例外:
public class NotFoundException404<TKey> : HttpResponseException
{
private string _message;
public NotFoundException404(TKey id) : base(StatusCodes.Status404NotFound)
{
_message = $"Nenhum objeto encontrado! ID solicitado: { id }";
}
public NotFoundException404(long id) : base(StatusCodes.Status404NotFound)
{
_message = $"Nenhum objeto encontrado! ID solicitado: { id }";
}
public NotFoundException404(string message) : base(StatusCodes.Status404NotFound)
{
_message = message;
}
public override string Message => _message;
}
此异常是从与HTTP其他异常相同的基本服务引发的,例如:
protected async Task DeleteAsync(TKey id)
{
var entidade = await GetEntidadeExclusaoAsync(id);
try
{
await _repository.DeleteAsync(entidade);
}
catch (SqlException e) when (e.Number == 547)
{
throw new ForeignKeyViolationException();
}
catch (Exception ex)
{
if (ex.InnerException != null
&& ex is SqlException
&& ((SqlException)ex).Number == 547)
throw new ForeignKeyViolationException();
}
}
那个不起作用的异常在我的过滤器中为空,我不知道为什么。有什么建议吗?这里的主要问题似乎是我很愚蠢。我停下来以更彻底的方式检查代码,问题不在于过滤器,而是我如何尝试提出ForeignKeyViolationException。这: 应该是这样的:
catch (Exception ex)
{
if (ex.InnerException != null
&& ex.InnerException is SqlException
&& ((SqlException)ex.InnerException).Number == 547)
throw new ForeignKeyViolationException();
else
throw ex;
}
德普
更新
johnny 5的答案更简洁,效果也更完美,这无疑是首选的解决方法:
catch (Exception ex) when ((ex.InnerException as SqlException)?.Number == 547)
{
throw new ForeignKeyViolationException();
}
看起来你已经找到问题的答案了。不过,我会努力建立在你的答案之上。可以使用when子句使函数更具可读性
catch (Exception ex) when ((ex.InnerException as SqlException)?.Number == 547) {
throw new ForeignKeyViolationException();
}
我认为您犯了一个错误,SqlExceptionex.InnerExceptionex应该这样读:SqlExceptionex.InnerException。请参阅我的答案以了解优化和改进readability@johnny5是的,我在传递代码时搞砸了,只是更新了我的答案。我会尝试一下你的外观,测试后再更新一次。我不知道这样的时候你还能用。事实上,直到上周我才知道你什么时候起床。顺便说一句,您遗漏了几个括号,编译器仅在ex.InnerException作为SqlException?时才允许。Number==547
catch (Exception ex)
{
if (ex.InnerException != null
&& ex.InnerException is SqlException
&& ((SqlException)ex.InnerException).Number == 547)
throw new ForeignKeyViolationException();
else
throw ex;
}
catch (Exception ex) when ((ex.InnerException as SqlException)?.Number == 547)
{
throw new ForeignKeyViolationException();
}
catch (Exception ex) when ((ex.InnerException as SqlException)?.Number == 547) {
throw new ForeignKeyViolationException();
}