2

我有一个 Web 应用程序:ExtJs 前端 - EntityFramework + SQL Server 作为后端。让我们看一下其中一种错误场景:

  • 我有用户名的数据库限制(名称必须是唯一的)
  • 我没有任何客户端验证(我应该吗?有没有办法使这种验证通用?)
  • 如果我尝试插入同名用户,服务器返回 500 错误。
  • 如果我从 IIS 开启的同一台机器上运行它 - 我会收到完整的错误消息(基本上是带有密钥冲突的 SQL 异常描述等),如果我从另一台机器上运行它 - 我只会收到 500 错误并且没有错误消息。

处理这个问题的最佳方法是什么?我需要以某种人类可读的格式告诉用户该错误。我真的不想在 IIS 上打开错误消息,因为这不是一个好习惯。

4

4 回答 4

2

我认为您在这里没有错误,而是违反了业务规则。

我喜欢区分这两种情况,首先是一些意外情况(例如数据库连接丢失),然后是您知道可能发生的一些情况。

对于错误,我认为适当的是以通用方式通知用户(例如,“发生意外错误”),因为用户无法更正也不需要详细信息。

另一方面,业务规则是用户可能理解并可以采取行动纠正的东西(这里是用户名约束)。所以应该通知用户。

在我从事的项目中,我们有一种异常,BusinessException. 我们抛出一条消息,指出问题出在哪里,并以人类可读的格式呈现。我们没有明确地尝试捕获这些异常,而是使用处理程序来管理它们。如果您使用的是 MVC,则可以使用扩展挂钩。

对于其他类型的异常,将堆栈跟踪记录在某处(即 EventViewer)是一个很好的做法,但不向用户提供详细信息。

在这种情况下,我会执行以下操作:

  • 有一个按钮检查名称以允许用户预先验证名称。
  • 验证名称的位置取决于您希望将应用程序的业务逻辑放在何处。在 DB 上,使用存储过程是一种方法,但如果您使用的是 EF,这意味着您要从数据访问中抽象出来。相反,您可以自己编写此验证,使用LINQ( 之类的Context.Users.SingleOrDefault(x => x.Name == name),然后检查它是否返回 null 或某个用户​​。您可能认为此验证不是必需的,因为您已经有了数据库约束,但是这样做,逻辑仍然存在您的应用程序的代码。
  • 从 EF 捕获异常可能会很麻烦,因为您需要检查 SQL 错误代码以确定它是违反约束还是其他错误。即使您确定了这一点,您也需要将消息转换为用户友好的消息。

我希望这对您的决定有所帮助!

于 2012-05-25T13:34:56.053 回答
1

首先,我建议您在向客户端上的服务器提交之前进行验证,通过向用户提供即时反馈是一种很好的体验。

其次,对于我使用的实际插入,您可以考虑的选项很少:

  1. 使用执行检查和插入的存储过程并返回新记录作为成功插入的确认,这很容易处理事务并处理存储过程中的所有问题,但是现在您拥有位于编译代码之外的功能
  2. 在您的插入过程中包装一个调用以首先在事务中进行验证并适当地处理它,为您提供编译的代码和较少的外部依赖关系(如存储过程),但是您对该层的事务锁类型有一些限制但可行
  3. 尝试插入并捕获异常,并适当处理,这是我最不喜欢的

我没有看到你提到更新UserName,如果你确实允许这个功能,你也必须在更新之前进行验证,因为你在插入时会出现同样的问题。

于 2012-05-25T12:48:14.870 回答
1

我没有任何客户端验证(我应该吗?有没有办法使这种验证通用?)

我会一直这样做。您可以使用 jquery ajax 调用服务器页面并检查那里的数据。这让用户在点击提交按钮之前就知道用户名不可用。这提供了更好的用户体验。这种方法避免了另一个服务器往返(带有所有表单数据的正常表单发布,然后收到错误)

如果我尝试插入同名用户,服务器返回 500 错误。

始终在您的代码中捕获异常并记录它。向用户显示有关错误的友好消息。永远不要向最终用户显示异常的堆栈跟踪。如果您使用的是 ASP.NET,请使用自定义错误页面功能。

于 2012-05-25T13:47:01.570 回答
1

如果您使用 DbContext,您可以通过自定义内置验证来验证唯一性。看看这篇博文:http: //blogs.msdn.com/b/adonet/archive/2011/05/27/ef-4-1-validation.aspx。最后有一个例子展示了如何做到这一点。

于 2012-05-25T15:58:53.627 回答