带参数的本地化错误消息

时间:2014-06-23 10:40:04

标签: c# asp.net exception-handling

场景1:想象一下,您的业务层中有一个复杂的检查或计算,并且由于某些数据错误或缺失,计算失败。例如,您捕获计算异常。

Sceneraio 2:想象一下,您在业务层中查询数据层(数据库),并捕获到丢失的记录异常。

任务:您现在位于业务层,挂在catch块中但尚未解决的异常。您希望通知用户出现错误,因为参数X与参数Y不匹配,您需要本地化错误消息(为简单起见,您有两种语言)。

问题:

  • a)如何将错误传播到表示层。
  • b)您如何本地化错误并将参数保留在消息中?例如:“亲爱的用户计算失败,因为数据X与数据Y不匹配”

建议的答案:

  • a)您从业务层中抛出另一个异常,将前一个异常作为内部异常。
  • b)这是我正在寻找的关键答案。我们假设您可以放弃参数值,因为它是一个Intranet应用程序,用户需要知道这些参数是错误的。

问题是关于应用程序设计 - 当代码中有一个点被捕获到异常时,如何“转换/本地化异常”或向用户显示已翻译/本地化的错误消息,并且多个消息可能存在多个异常

异常消息采用统一语言,假设为英语。

2 个答案:

答案 0 :(得分:1)

我这样做的通常方法是本地化格式字符串。您的资源包括格式字符串,如下所示:

string errorString "Dear user the computation has failed because data {0} does not match data {1}";

抛出此异常或显示错误时,只需插入数据

即可
string.Format(errorString, dataX, dataY);

编辑:如果您希望将统一语言中的异常文本放在一起,并且以后不想将异常类型映射到资源字符串,那么最好的选择是提供资源字符串到您的异常以及数据,或者让您的异常同时携带原始消息和翻译的消息。

映射问题的另一个选择是您可以使用反射。这样,您可以使用您的异常类型并在资源中查找所述类型,而无需显式映射它们。您将转到您的资源并查找名为的属性,例如" Error_MyCustomException"。这将为每个Exception类型提供一个自定义消息,您需要存储的只是数据。

答案 1 :(得分:1)

我们在申请中这样做。我们采取的方法是:

  1. 在服务层中没有错误。允许所有异常传播回进行原始调用的表示层方法。

  2. 在数据访问层中抛出自定义异常。通常,在查询数据库时发生数据访问异常时,会引发特定于数据库的错误。在数据访问层中捕获该异常,但将其包装在自定义异常中。我们有一个名为DataAccessException的枚举属性,它指示导致错误的数据访问层调用,另一个指示错误原因是否与访问相关(权限不足),或者因为数据库引发了错误错误。

  3. 捕获表示层中的所有错误。在调用服务层的表示层方法中,有一个try-catch块。对于每个异常类型,通常会有一个catch子句,您希望它们由较低层中的代码抛出。在该catch块中,您可以创建本地化消息,将其记录到事件日志中(如果有),并将错误显示给用户。

  4. 所有可本地化的字符串都应该是资源字符串。这不是硬性规则,但使用资源字符串方法意味着它很容易添加对Windows支持的其他语言的支持未来。您为每个不会更改的字符串定义资源标识符。每个字符串所用的参数数量也不会改变。所有这些变化都是措辞以及" {0}"," {1}"等参数出现在字符串中。

  5. 修改

    我在这里回复你的评论,因为回复的时间比我在一条评论中的回答要长。

    根据我在特定catch块中处理的异常来创建本地化消息。我尝试将错误消息设为可读的。也就是说,你必须假设读者完全不了解任何编程知识。你描述了一般来说出了什么问题;最好不要提到确切的例外。例如,当您尝试打开文件时,FileNotFoundException的消息应该说是"文件名为" {0}"无法找到。请确保您正确输入了文件名。"如果您家中的某个人不是程序员,那么请考虑一下如何向他们解释问题&你可能会有一个好消息。

    至于提供它的资源键,我使用命名约定。对于我们的MVC Web应用程序,约定是< Controller> < Action> <消息名称>。一旦定义了密钥,代码总是使用密钥通过请求与VS构建的ResourceManager中的密钥同名的属性来检索消息。

    在构建资源字符串时由VS创建的ResourceManager类使用区域设置来确定要检索的本地语言消息字符串。返回的字符串以及所需的任何参数将传递给string.Format,并显示或记录结果。

    我们的代码中有一条规则,即消息字符串的参数总是不需要翻译成另一种语言的东西。也就是说,用户输入的字符串,或数字或日期都可以,但枚举值不是。这是因为我们的Web应用程序显示从自身和Windows WPF应用程序生成的审核消息,并且不知道WPF应用程序中的任何枚举。由于ResourceManagerpartial类,因此您可以轻松地向其添加方法,以便在您想要的情况下本地化您的枚举。这掌握在你的掌控之中。然后,您可以调用该方法来本地化枚举值,然后将其传递给您需要执行此操作的string.Format