【问题标题】:MVC3 Views : Handling null models with finesseMVC3 视图:巧妙地处理空模型
【发布时间】:2012-03-01 15:16:56
【问题描述】:

我经常遇到项目中的视图抛出空引用异常的情况。

@model Johnny.Application.TestModel
<div>@(Model.SomeText)</div>

如果 Modelnull,则会引发错误。

但是人们是如何处理这个问题的呢?我当然不会在任何地方看到代码示例,其中丑陋的空检查在视图中乱扔代码。这让我相信大多数时候,控制器不应该返回空模型。但是,您如何才能更巧妙地执行此操作呢?

现在,一旦有人不小心导致控制器返回 null 模型,视图模型就会崩溃并看起来有问题。实际上,这是控制器的错。视图甚至可能无法“抓住”问题,只有在模型的成员碰巧被使用时才会这样做(当然,这是大多数时候)。

由于各种原因,某些视图可能想要处理空值。不过,我不希望这是大多数情况。显然这是在视图和控制器之间设置一些“合同”的问题。

我不喜欢我见过的选项:

  1. 每次使用时检查模型是否为空。 很蹩脚
  2. 一个大 if 语句用一个空模型包裹整个视图 查看。想想浪费的代码空间。跛脚!
  3. 在顶部添加 if 检查并带有 throw 。不坏,但看起来很傻。有点跛脚。

我很想知道是否存在类似的选项来设置“无空值”合同:

  • 控制器方法上的属性,如 [NoNullModels]。我怀疑这是否存在,因为我认为控制器不知道它连接到什么视图。
  • 在视图中,@MVC3.HeyDontAllowNulls 之类的指示器或其他引发异常的标准方式(如上面的选项 3)

【问题讨论】:

  • 为什么还要返回一个空模型?
  • 你试过@Html.DisplayFor(m =&gt; m.SomeText)
  • 鉴于将模型传递给视图是控制器的工作,不应该处理空模型而不是视图吗?由于控制器不遵守协议而使视图复杂化似乎不是正确的方法。
  • 关于代码样例话题,网上99%的代码样例都没有异常处理和输入验证。部分是因为懒惰,部分是因为它会混淆代码示例所说明的点。
  • 我还会考虑使用某种全局异常日志记录,例如 ELMAH,并确保您有一个友好的错误页面,以便在出现问题时向用户显示。然后,您可以密切关注 ELMAH 日志并修复代码未预料到的严重错误。

标签: c# asp.net asp.net-mvc-3 razor


【解决方案1】:

我在这里Should one try to guard against null reference exceptions / index out of bounds exceptions in MVC views? 提出了类似的问题,并得到了很好的回应。简而言之,最好在您的控制器甚至单元测试中添加空检查,而不是在您的视图中。

【讨论】:

  • 我没有想到单元测试方法,这对于他们的实用程序来说是一个很好的场景。由于我不“拥有”所有代码,我将无法使所有控制器都可单元测试,因此我希望在这些情况下为视图找到一个后备选项。
  • 我也承认,如果我有一个高度共享的视图,它是由许多操作方法呈现的,我肯定会想在视图本身的一个地方添加一个空检查,而不是在其他十几个地方,即使我确实拥有所有代码。您可以将其称为对 DRY 原则的遵守,但会稍微违反 MVC 关注点分离。
  • 越想越觉得view是加点东西的好地方。一个原因是单个控制器操作可以路由到几个不同的视图。在控制器端修复它是无效的,因为它迟早会出现泄漏(就像我一直遇到的情况一样!)
【解决方案2】:

这里有很多偏好,你可以做的一些是:

  1. 在您的数据层中抛出 RecordNotFoundException(自定义异常)并让全局异常过滤器捕获此异常
  2. 检查从您的存储库返回的空值并根据具体情况进行处理
  3. 装饰您的控制器以在不是 CREATE 方法(或您认为合适的任何规则)的 GET 方法上查找空模型,并使用操作过滤器属性在 OnActionExecuted 中检查这一点

即使是我的“CREATE”视图通常也会有一个模型,即使是空的(尽管其中经常有一个 IEnumerable),所以它们应该总是有模型。

【讨论】:

    【解决方案3】:

    我有时会在需要它的部分视图中检查是否存在空值。

    有时我也会在我的控制器中创建默认值,如果有空值取决于你想要做什么以及什么是可以接受的。

    例如,我有一个案例,人们订阅某些内容并设置通知。如果他们没有通知,我的模型的子对象为空。我不想设置默认值,所以我在那里检查。在其他部分我只使用默认值。

    【讨论】:

      猜你喜欢
      • 2015-03-11
      • 1970-01-01
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      • 2011-02-03
      • 1970-01-01
      • 1970-01-01
      • 2014-06-17
      相关资源
      最近更新 更多