我已经读过(here),执行Try / Catch块并避免Web API设置中的异常不是一个好主意。但是,如果您想捕获并记录应用程序中发生的错误,那么尝试/捕获不是解决问题的最佳方法吗?这是我在应用程序中所做的一个示例-我很好奇是否有人有更好的方法。我的ErrorHander
类将错误保存到数据库,并通过电子邮件将错误的详细信息发送给管理员。
namespace MyApp.Controllers
{
[Route("api/[controller]")]
public class AuthController : Controller
{
private readonly IAuthRepository _repo;
private readonly IErrorHandler _errorHandler;
private AuthController(IAuthRepository repo, IErrorHandler errorHandler) {
_errorHandler = errorHandler;
}
[Authorize]
[HttpPut("changePassword")]
public async Task<IActionResult> ChangePassword(
[FromBody] UserForChangePasswordDto userForChangePasswordDto)
{
var userFromRepo = await _repo.Login(userForChangePasswordDto.Username,
userForChangePasswordDto.OldPassword, null);
try
{
//logic to update user's password and return updated user
return Ok(new { tokenString, user });
}
catch (Exception ex)
{
// emails error to Admin, saves it to DB, then returns HttpStatusCode
return await _errorHandler.HandleError(
HttpStatusCode.InternalServerError, Request, new Error
{
Message = ex.Message,
StackTrace = ex.StackTrace,
User = userFromRepo != null ? userFromRepo.Username : "Invalid User"
});
}
}
}
}
答案 0 :(得分:1)
我有一些建议:
尽可能避免使用try..catch
。例如,使用诸如TryParse
,TryCreate
等的方法,而不是引发异常的方法。 *OrDefault
LINQ方法也是如此,例如始终使用SingleOrDefault
而不是Single
,依此类推。基本上,如果有一种方法可以避免引发异常,请使用该方法。
当您确实需要处理异常时,请在抽象中进行处理,而不是在应用程序代码中进行处理。例如,假设//logic to update user's password and return updated user
行正在使用您的IAuthRepository
。您正在调用的仓库的方法本身不应引发异常。如果内部代码引发了异常,请捕获那里并处理它那里。然后,您的方法本身可以返回类似布尔值的内容,您可以使用它们来确定操作是否成功并相应地分支。尽管实际的错误处理逻辑(电子邮件管理员等)包含在您的IErrorHandler
抽象中,但是您的应用程序代码仍在使用该代码,并且依赖于此,这是不必要的领域知识。
捕获异常时,捕获特定于 的异常。您应该确切地知道正在捕获什么以及为什么。捕获像Exception
这样通用的东西通常是延迟编码的标志。您甚至可能根本不知道是否可以返回异常,但是您仍然在使用性能降低的try..catch
块。在某些情况下,捕获任何可能的异常可能是适当的,但是,您应该始终重新抛出该异常。吞下所有可能的例外都是一个巨大的禁忌。如果您觉得无法重新引发该异常,则应该针对特定的异常。
try
{
// do something
}
catch (Exception e)
{
// log exception
throw;
}
将错误处理与请求处理分开。您的应用只需要返回请求的响应。它不应该在意诸如向管理员发送电子邮件之类的东西。您需要某种记录,指出发生了问题,这是可以理解的,但是简单的日志记录就足以解决问题,而且重量更轻。如果您想向管理员发送电子邮件,则可以设置单独的服务以在适当时监视日志和生成电子邮件,从而适当地带走该过程。
答案 1 :(得分:1)
如果您想捕获异常并对异常做一些常规的事情,例如您在示例中所做的,那么您的方式不是ASP.NET中的好方法:)
当您有多个控制器并且每个控制器内部都有多个动作时,您将有很多代码重复。
ASP.NET Core允许您创建一个Filter,您可以在其中放置所有此类逻辑。这意味着您将只拥有一个地方来处理未捕获的异常。 您应该彻底了解IExceptionFilter
所提供的可能性