【问题标题】:Do you catch expected exceptions in the controller or business service of your asp.net mvc application您是否在您的 asp.net mvc 应用程序的控制器或业务服务中捕获了预期的异常
【发布时间】:2012-07-02 19:02:49
【问题描述】:

我正在开发一个 asp.net mvc 应用程序,其中 user1 可以删除 user2 之前刚刚加载的数据记录。 User2 要么更改这个不存在的数据记录(更新),要么在另一个违反外键约束的表中使用此数据进行插入。

你在哪里捕捉到这样的预期异常?

在您的 asp.net mvc 应用程序的 Controller 中还是在业务服务中?

只是一个旁注:我只在这里捕获 SqlException,如果它是一个 ForeignKey 约束异常,告诉用户另一个用户已经删除了某个父记录,因此他不能创建测试计划。但是这段代码还没有完全实现!

控制器:

  public JsonResult CreateTestplan(Testplan testplan)
  {
   bool success = false;
   string error = string.Empty;

   try
  {
   success = testplanService.CreateTestplan(testplan);
   }
  catch (SqlException ex)
   {
   error = ex.Message;
   }
   return Json(new { success = success, error = error }, JsonRequestBehavior.AllowGet);
  }

或

商业服务:

public Result CreateTestplan(Testplan testplan)
        {
            Result result = new Result();
            try
            {
                using (var con = new SqlConnection(_connectionString))
                using (var trans = new TransactionScope())
                {
                    con.Open();

                    _testplanDataProvider.AddTestplan(testplan);
                    _testplanDataProvider.CreateTeststepsForTestplan(testplan.Id, testplan.TemplateId);
                    trans.Complete();
                    result.Success = true;
                }
            }
            catch (SqlException e)
            {
                result.Error = e.Message;
            }
            return result;
        }

然后在控制器中:

public JsonResult CreateTestplan(Testplan testplan)
      {
       Result result = testplanService.CreateTestplan(testplan);      
       return Json(new { success = result.success, error = result.error }, JsonRequestBehavior.AllowGet);
      }

【问题讨论】:

    标签: asp.net-mvc exception-handling


    【解决方案1】:

    应检查并正确显示外键约束违规。您可以轻松检查相关表中的行是否存在并显示正确的消息。行更新也可以这样做。服务器返回受影响的行数,因此您知道会发生什么。

    即使您不进行这些检查,您也应该捕获 SQL 异常。对于普通应用程序用户来说,关于违反约束的消息毫无意义。此消息适用于开发人员,您应该使用 ELMAH 或 Log4Net 库记录它。用户应该会看到类似“我们很抱歉。此行可能已被其他用户修改,您的操作无效”的消息。如果他向开发者询问这件事,开发者应该检查日志并查看原因。

    编辑

    我认为您应该检查服务中的错误。控制器不应该知道数据访问层。对于控制器,将数据存储在 SQL 数据库还是文件中都没有关系。文件可以抛出文件访问异常,SQL 有其他的。控制器不应该担心它。您可以在服务中捕获数据访问层异常并抛出服务层专用类型的异常。控制器可以捕获它并显示正确的消息。所以答案是:

    public class BusinessService 
    {
        public Result CreateTestplan(Testplan testplan)
        {
            Result result = new Result();
            try
            {
                using (var con = new SqlConnection(_connectionString))
                using (var trans = new TransactionScope())
                {
                    con.Open();
    
                    _testplanDataProvider.AddTestplan(testplan);
                    _testplanDataProvider.CreateTeststepsForTestplan(testplan.Id, testplan.TemplateId);
                    trans.Complete();
                    result.Success = true;
                }
            }
            catch (SqlException e)
            {
                ....log in ELMAH or Log4Net using other logging framework...
                throw new ServiceException("We are sorry. Your operation conflicted with another operation in database. It has been cancelled.");
            }
            return result;
        }
    }
    

    【讨论】:

    • 你说的很有帮助,但我仍然想念你说为什么我应该在控制器或服务中捕获异常。
    • 1.) “Controller can catch it...” 但是我的结果类已经过时了。然后我的控制器中有错误,可以确定是否发生异常。有时我什至不得不检查内部异常消息。 2.) 我宁愿在服务中捕获 2 个自定义异常类型,它们可能来自 2 个不同的数据提供者方法。你怎么看?
    • 3.) "throw new ServiceException("我们很抱歉。您的操作与数据库中的另一个操作冲突。它已被取消。");"在这里获取异常代码号不是很好吗?例如,获取并发/fk 约束违规/重复插入的代码,这样我就可以向用户显示更详细的错误消息,而不是说:“您的操作冲突 bla bla”??
    • @Pascal: 1) 是的,你的 Result 类已经过时了。也许有时您必须检查内部异常,但这是您,而不是普通用户。普通用户不会理解内部异常。您应该将其记录在其他地方,而不是向用户显示。 2)我不明白。 3)你可以显示数字,但为什么呢?您不希望用户使用外键约束给您打电话。它发生了,用户必须理解它,而不是投资。对于不寻常的错误,真正的错误,你有应用程序日志,你应该监控它们。
    • 1.) 同意 2.) 算了,我认为你的建议很好。 3.)不想向用户显示数字,它只是为了我个人,BLL 通过数字知道当他捕获 DAL-SqlException 时要抛出什么自定义异常。谢谢大家。
    猜你喜欢
    • 2019-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多