ASP.Net MVC尝试捕获最佳实践

时间:2011-04-20 11:26:25

标签: asp.net-mvc

有谁能请指导我在ASP.NET MVC中处理异常的最佳做法是什么?

  1. 控制器?
  2. 模型?
  3. Model(包含EF逻辑,即保存,更新等)抛出任何异常并捕获Controller?

2 个答案:

答案 0 :(得分:11)

在任何方法或代码块中,您可能会遇到特定的异常(与数据库或外部服务交互,可能会或可能不会等等)将该代码包装在Try / Catch中以捕获特定的异常(s)有问题。您想要确切地知道发生了什么样的异常才能正确处理它们。 (当然,使用Finally块来处理任何开放资源。)如何正确处理它们取决于您以及您希望应用程序的行为方式。

你绝对应该有一个全局异常处理来捕获任何意外的错误。在点,未处理的异常应该向用户冒泡。全局异常处理程序应该只向用户显示友好的错误消息,并应记录异常并通知您发生的情况。通常,一个好的目标是识别异常并添加错误处理代码,以便在它冒泡到全局之前将其捕获到其本地化状态。随着时间的推移,目标应该是尽可能少的全局异常,并且任何可能产生异常的代码都有自己的错误处理来防范这些情况。

后者的一个例子可能就像接收null参数的特定方法一样简单,在使用这些参数之前要检查它们。但是,您要避免的一件事是对逻辑流使用异常处理。例如......

假设您有一个将自定义对象作为参数的方法:

public MyMethod(MyObject obj)
{
  // ...
}

您的原始代码假定obj始终具有值。但是,经过一段时间的生产后,您会发现obj有时是null并且它正在从该方法中抛出NullReferenceException,该方法正被全局异常处理程序捕获。 / p>

您可能想要将MyMethod中的代码包装在自己的Try / Catch块中以捕获该异常。这不一定是个好主意(尽管可能存在这种情况)。相反,您需要在方法开头检查null

public MyMethod(MyObject obj)
{
  if (obj == null) throw new ArgumentNullException("obj can not be NULL");
  // ...
}

这更好地封装了方法,并允许它抛出受控异常。例外不是坏事,只有意外的例外。请注意,上面的内容仍然会抛出异常,这个异常仍会冒泡到全局处理程序。因此,在Try / Catch块中将调用包装到此方法中也是一个好主意,以便捕获ArgumentNullException并相应地处理它。也许调用此方法的代码可以修复null引用并再试一次,也许它可以尝试别的东西,等等。如果可能的话,你仍然不希望它冒泡到全局处理程序,因为这已成为“预期的”异常,可以据此处理。

当然,您仍然希望避免在上面的示例中抛出/捕获预期的异常,因此在调用方法之前应该对null进行类似的检查,以便甚至不调用该方法。

如果对象是null,您可以直接向用户显示错误消息并记录错误并尽可能多地通知您有关事物状态的信息,以便您可以研究它为什么{{{ 1}}并修复它。根据应用程序的逻辑,当时null可能是该对象的完全可接受的状态。如果是,请检查它是否为null并且不打扰调用该方法。继续照常进行。

这是很多错误检查和处理代码,但这是一件好事。

编辑:有关异常处理的另一个注意事项是,如果您当时可以实际处理,则应该捕获异常。如果方法无法在内部处理它,请将异常从方法冒泡到调用方法,依此类推。因此,应该到达全局处理程序的唯一异常是您无法在代码中的任何位置实际处理的异常(这就是为什么修复和防止全局异常的好目标)。

在这种情况下,“处理”意味着能够真正做一些事情。也许有些东西只是记录并继续进行,也许某些东西是执行一些特定的逻辑等等。但是捕获,记录和重新抛出是糟糕的设计。如果你无法从异常中恢复,那就让它冒泡。

答案 1 :(得分:1)

最好的方法是全局捕获异常,使用Elmah记录它。否则,您将不得不将所有异常放在每个控制器代码中,这将是很多重复,特别是对于CRUD操作