C# 在Web API中尝试/捕获块/避免异常不是一个好主意?

C# 在Web API中尝试/捕获块/避免异常不是一个好主意?,c#,exception,asp.net-core,asp.net-core-webapi,C#,Exception,Asp.net Core,Asp.net Core Webapi,我已经读到,在Web API设置中执行Try/Catch块并避免异常不是一个好主意。然而,如果你想捕捉并记录应用程序中发生的错误。。。试一试不是最好的方式吗?下面是我在应用程序中所做的一个例子——我很好奇是否有人有更好的方法。我的ErrorHander类将错误保存到数据库,并通过电子邮件向管理员发送错误详细信息 控制器 我有几点建议: 尽可能避免完全抓住。例如,使用TryParse、TryCreate等方法,而不是抛出异常的方法。*OrDefault LINQ方法也是如此,例如始终使用Singl

我已经读到,在Web API设置中执行Try/Catch块并避免异常不是一个好主意。然而,如果你想捕捉并记录应用程序中发生的错误。。。试一试不是最好的方式吗?下面是我在应用程序中所做的一个例子——我很好奇是否有人有更好的方法。我的ErrorHander类将错误保存到数据库,并通过电子邮件向管理员发送错误详细信息

控制器
我有几点建议:

尽可能避免完全抓住。例如,使用TryParse、TryCreate等方法,而不是抛出异常的方法。*OrDefault LINQ方法也是如此,例如始终使用SingleOrDefault而不是Single等。基本上,如果有办法避免抛出异常,请使用该方法

当您确实需要处理异常时,请在抽象中处理,而不是在应用程序代码中处理。例如,大概更新用户密码并返回更新的用户行的//逻辑正在使用IAuthRepository。您正在调用的repo方法本身不应引发异常。如果内部代码引发异常,则在那里捕获并处理它。然后,您的方法本身可以返回类似布尔值的内容,您可以使用它来确定操作是否成功,并相应地进行分支。尽管实际的错误处理逻辑email admin等包含在IErrorHandler抽象中,但您的应用程序代码仍在使用它,并且依赖于它,这是不必要的领域知识

捕获异常时,捕获特定的异常。你应该确切地知道你抓住了什么以及为什么。捕获像异常这样通用的东西通常是延迟编码的标志。您可能根本不知道是否可以返回异常,但您仍然在使用性能耗尽的try..catch块。在某些情况下,捕获任何可能的异常可能是合适的,但是,您应该始终重新抛出异常。吞下每一个可能的异常都是一个巨大的禁忌。如果你觉得你不能重新抛出异常,那么你应该针对一个特定的异常

try
{
    // do something
}
catch (Exception e)
{
    // log exception
    throw;
}
将错误处理与请求处理分开。你的应用只需要返回请求的响应。它不应该关心像给管理员发电子邮件之类的事情。可以理解,您需要某种类型的出错记录,但简单的日志记录就足够了,而且重量要轻得多。如果你想给管理员发电子邮件,你可以设置一个单独的服务来监控你的日志,并在适当的时候生成电子邮件,这将使这个过程适当地超出范围


我有几点建议:

尽可能避免完全抓住。例如,使用TryParse、TryCreate等方法,而不是抛出异常的方法。*OrDefault LINQ方法也是如此,例如始终使用SingleOrDefault而不是Single等。基本上,如果有办法避免抛出异常,请使用该方法

当您确实需要处理异常时,请在抽象中处理,而不是在应用程序代码中处理。例如,大概更新用户密码并返回更新的用户行的//逻辑正在使用IAuthRepository。您正在调用的repo方法本身不应引发异常。如果内部代码引发异常,则在那里捕获并处理它。然后,您的方法本身可以返回类似布尔值的内容,您可以使用它来确定操作是否成功,并相应地进行分支。尽管实际的错误处理逻辑email admin等包含在IErrorHandler抽象中,但您的应用程序代码仍在使用它,并且依赖于它,这是不必要的领域知识

捕获异常时,捕获特定的异常。你应该确切地知道你抓住了什么以及为什么。捕获像异常这样通用的东西通常是延迟编码的标志。您可能根本不知道是否可以返回异常,但您仍然在使用性能耗尽的try..catch块。在某些情况下,捕获任何可能的异常可能是合适的,但是,您应该始终重新抛出异常。吞下每一个可能的异常都是一个巨大的禁忌。如果你觉得你不能重新抛出异常,那么你应该针对一个特定的异常

try
{
    // do something
}
catch (Exception e)
{
    // log exception
    throw;
}
将错误处理与请求处理分开。你的应用只需要返回请求的响应。它不应该关心像给管理员发电子邮件之类的事情。可以理解,您需要某种类型的出错记录,但简单的日志记录就足够了,而且重量要轻得多。如果你想给管理员发电子邮件,你可以设置一个单独的服务来监控你的日志,并在适当的时候生成电子邮件,这将使这个过程适当地超出范围


如果您想捕获异常和d o一些一般性的事情,如您在示例中所做的,则您的方式不是ASP.NET中的好方式:

当您有多个控制器和每个控制器内的多个操作时,您将有大量代码重复

ASP.NET核心允许您创建一个可将所有此类逻辑放入其中的应用程序。这意味着您只有一个地方可以处理未捕获的异常。
您应该明确地了解一下随

提供的各种可能性。如果您希望捕获异常并对其执行一些常规操作,就像您在示例中所做的那样,那么您的方式在ASP.NET中不是好的方式:

当您有多个控制器和每个控制器内的多个操作时,您将有大量代码重复

ASP.NET核心允许您创建一个可将所有此类逻辑放入其中的应用程序。这意味着您只有一个地方可以处理未捕获的异常。
您应该明确地了解一下您链接到的答案所提供的可能性,该答案说最好不要捕获致命异常,并在您能够处理其他异常时正确处理它们。在您的情况下,您是通过记录异常来处理异常的,但是,这应该由Web API的全局错误处理程序来处理,而不是在控制器中。处理Web API中的错误是一个跨领域的问题。每个控制器操作方法都需要某种形式的错误处理。WebAPI为您拥有的每个控制器提供了实现这一点的工具。我认为链接帖子完美地回答了你的问题。虽然它不包含每种情况的任何示例,但您通常应该避免try/catch,而不仅仅是记录它并忘记它,而是在root中避免它。那么,在您的示例中,在ChangePassword中可能会出现什么错误?在同一控制器的其他方法中不会出现什么错误?我认为,这种特殊的捕获应该是全球性的,而不是在方法上。方法应该总是返回Ok,如果业务规则没有这样说的话。最好查看ASP.NET核心文档,而不是上面链接的ASP.NET Web Api文档。根据这些建议,我最终在启动类的app.UseExceptionHandler中实例化了我的ErrorHandler类。这要容易得多。然后我仍然可以使用相同的ErrorHandler类给出并记录自定义响应。您链接到的答案说,最好不要捕获致命异常,并在可以处理其他异常时正确处理它们。在您的情况下,您是通过记录异常来处理异常的,但是,这应该由Web API的全局错误处理程序来处理,而不是在控制器中。处理Web API中的错误是一个跨领域的问题。每个控制器操作方法都需要某种形式的错误处理。WebAPI为您拥有的每个控制器提供了实现这一点的工具。我认为链接帖子完美地回答了你的问题。虽然它不包含每种情况的任何示例,但您通常应该避免try/catch,而不仅仅是记录它并忘记它,而是在root中避免它。那么,在您的示例中,在ChangePassword中可能会出现什么错误?在同一控制器的其他方法中不会出现什么错误?我认为,这种特殊的捕获应该是全球性的,而不是在方法上。方法应该总是返回Ok,如果业务规则没有这样说的话。最好查看ASP.NET核心文档,而不是上面链接的ASP.NET Web Api文档。根据这些建议,我最终在启动类的app.UseExceptionHandler中实例化了我的ErrorHandler类。这要容易得多。然后我仍然可以使用同一个ErrorHandler类来提供和记录自定义响应。