关于ASP.NET MVC:ASP.NET MVC – 异常抛出?

ASP.NET MVC - Exception throw?

我有一个通用的存储库 - 如果存储库能够抛出异常还是我应该保持愚蠢? 如果我选择从中抛出异常,那么服务层是否应该捕获它并在转到Controller之前抛出一个带有更友好消息的异常?

  • Pos1:Repository(Throw)=> Service(Catch,Throw new)=> Controller(Catch)
  • Pos2:Repository => Service(Throw)=> Controller(Catch)

绝对是选项1。

我也会在你的思想中用"关注点分离"取代"哑巴"一词。存储库没有理由变得愚蠢。它有一项工作要做,这将涉及例外。

它还涉及抛出它们有两个原因:

  • 打包消费代码发生的真实错误。

  • 在特定条件下抛出异常,违反了您希望此类执行的操作。这些条件可能不涉及框架抛出的异常,并且可能仅与您希望存储库具有的"智能"相关。

  • 存储库必须涉及封装所有这些智能,让调用代码只需要知道如何处理有限的异常集。否则,您的调用代码需要处理,例如,完整的LINQ异常,将其耦合到应该是存储库的独占域的技术。

    因此,Repositiory智力的一部分必须抛出与其特定目的相关的众所周知但有限的例外情况。

    如果您有服务层,则相同的推理适用于服务层。它需要以完全相同的方式处理异常:封装特定于其任务的"智能"。而且,控制器也是如此。它应该根据自己的目的和关注点解释它从服务层(如果有的话)收到的例外情况。

    所以关注点分离,但从不愚蠢。甚至不是静音:每个层都需要尖叫。


    Should the repository be able to throw
    exceptions or should I keep it dumb?

    是的 - 存储库应该能够抛出异常。保持"愚蠢"的东西并不意味着它不是完??全自我意识:)

    "异常应该例外"的警告仍然适用 - 您可能会发现这个"创建更多例外异常"文章,它也与您的问题相关。

    If I chose to throw exceptions from
    it, should the service layer then
    catch it and throw an exception with a
    more friendly message before it goes
    to the Controller?

    一般来说,我没有重新抛出异常,尽管这样做是有好处的。一个实用的中途宿舍就是为那些你想要出于某种原因优雅处理的异常类型做到这一点。

    如果您正在使用Ms Ent Libs应用程序日志记录块,您可以设置一个策略(通过配置),允许您控制发生异常时发生的情况 - 重新抛出它们或其他方式;因此,这将是一种有用的方法,可以阻止将自己硬编码为特定的结果。

    这也许会引起人们的兴趣:例外真的是异常错误吗?


    一般来说,如果查询没有返回数据,则只需从存储库返回null。如果愿意,您可以在将数据发送到视图之前测试存储库中的null。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public ActionResult Details(int id) {

        Dinner dinner = dinnerRepository.FindDinner(id);

        if (dinner == null)
            return View("NotFound");
        else
            return View("Details", dinner);
    }

    http://nerddinnerbook.s3.amazonaws.com/Part4.htm

    对于编辑,我会让您的数据访问层或您的存储库抛出异常,并在控制器中捕获它,如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(int id, FormCollection formValues) {

        Dinner dinner = dinnerRepository.GetDinner(id);

        try {

            UpdateModel(dinner);

            dinnerRepository.Save();

            // Success!
            return RedirectToAction("Details", new { id=dinner.DinnerID });
        }
        catch {

            // Old-school data validation from ASP.NET MVC 1.0
            foreach (var issue in dinner.GetRuleViolations()) {
                ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
            }

            // Return original view, so user can correct errors.
            return View(dinner);
        }
    }

    http://nerddinnerbook.s3.amazonaws.com/Part5.htm