【问题标题】:Abort/skip/cancel the rendering of a Razor view中止/跳过/取消 Razor 视图的渲染
【发布时间】:2014-09-09 10:56:59
【问题描述】:

许多开发人员都这样做:

public void foo() {
  if (flag) {
    // do stuff
  }
}

我更喜欢“早点回来”,所以这样做:

public void foo() {

  if (!flag) return;

  // do stuff

}

在 ASP.NET-MVC Razor 视图中,中止/跳过/取消视图/部分视图呈现的正确方法是什么?例如如何转换:

@if (flag) {
  // do stuff
}

到这样的事情:

@if (!flag) { /* what do I do here to abort/skip/cancel the rendering? */ }

// do stuff

我尝试过使用returnRequest,但我不确定这会如何影响流程。这样做的正确方法是什么?

【问题讨论】:

  • 如果使用 "abort" 表示您想根据该标志排除某些内容,那么您无事可做,只需使用 if 来分隔这些部分(最终它甚至可能从该行到文件结尾)。很快它就会变得难以理解,因此您可以使用部分视图。如果您需要删除/跳过/取消页面创建(例如重定向到另一个页面或显示完全不同的内容),那么 您在错误的地方进行了检查。在您的控制器中执行此操作,它会选择正确的视图,而视图不会意识到这种逻辑。
  • @AdrianoRepetti 都是真的。但我仍然想这样编码。视图中总会有条件结构,这是不可避免的。渲染并不神奇,Razor 中有一些组件可以读取视图并吐出我们的 HTML——必须有一种方法可以在该过程的早期返回。
  • @hbob 实际上,视图被编译成一个类(我相信当应用程序启动时),然后在渲染管道期间执行类中的一个方法 - 它不起作用与您认为我怀疑的方式完全一样,并希望能解释为什么无法从 Razor 视图中尽早返回...
  • @TrueBlueAussie 不同意。这根本不是指导方针,而是风格问题。 “早退”已成定局。很多开发人员都是这样编码的。我们的确是。避免混乱的条件是一件好事,因为它使您的代码阅读变得容易。如果您认为它使代码难以阅读,那么您的函数可能太长而无法开始。
  • @TrueBlueAussie 对于您向我展示的每一项声称早返不好的“研究”,我会见到您并提出一项“研究”,表明它是好的。就像我说的,这是风格和偏好的问题。此外,这件事只是与问题相切。

标签: asp.net asp.net-mvc razor


【解决方案1】:

正如我上面提到的,您可以简单地发出return

我记得 cshtml 文件是在运行时编译的,其中包括所有内联代码以及静态 html。这意味着从理论上讲,我希望任何代码都保持原样,而不是以任何方式进行转换。

如果你这样做:

@if (!flag) { return; }

// do stuff

按预期工作(至少对我来说很好)。我只是想知道这是否会导致任何意外的副作用。

【讨论】:

  • +1 我的赞成票,但我不会在任何页面中使用它(如果您有 20 行功能,尽早返回是好的 IMO,但是 - 通常 - cshtml 页面更长且更复杂,这正是原因单返回点过去一直在使用)。无论如何都赞成,即使我不欣赏它,因为我什至不知道它可能有用!快速浏览一下使用 Reflector 反汇编生成的代码,似乎没有(可见的)副作用。
  • +1 表示“你每天都会学到新东西”,但是是的 - 不要以为我会用这个 ;-)
  • @AdrianoRepetti 感谢您的理解!你上面说的是真的,我 99% 的时间都遵循它。但是在编程和生活中一样,总是有 1%,所以了解环境并有足够的经验在不破坏系统的情况下改变规则是件好事。没想到拆开看看会发生什么,grazie!
  • @hbob 如果你在那里发现一些有趣的东西,请更新你的帖子,快速浏览一下,似乎 return 只是退出渲染功能,但我没有看到/检查 exotic 功能和/或有或没有布局。
  • @AdrianoRepetti:在我作为开发人员的职业生涯早期,我总是试图在我的方法/成员中获得一个(或两个)“回报”点。因为这是每个人都被告知要做的事情。事实证明,试图实现这一目标最终会产生太多的代码嵌套。你真的不应该为了实现那个过时的原则而改变或牺牲合理的代码流。在现代编程中,共识是如果你可以退出一个方法,那就去做。而且越早越好。而且你甚至不需要计算你有多少回报,只要你的重点是减少代码嵌套。无论如何,我的 0.02 美元。
【解决方案2】:

如果使用 "abort" 您的意思是您想根据该标志排除某些内容,那么您无事可做,只需使用if 来分隔这些部分(最终它甚至可能来自那个行到文件末尾)。像这样:

 @if (Model.User.HasEditingPrivileges)
 {
     <input type="button" id="edit" value="Edit"/>
 }

很快就会变得难以理解,因此您可以为此使用部分视图(尤其是当您必须包含/排除的块很大时):

 @if (Model.User.HasEditingPrivileges)
 {
     Html.RenderPartial("EditSection");
 }

如果您需要删除/跳过/取消页面创建(例如重定向到另一个页面或显示完全不同的内容),如下所示:

@if (!Model.User.hasEditingPrivileges)
{
    // Ooops, he shouldn't see this page, go back to Home!
}

那么你在错误的地方进行检查。在您的控制器中执行此操作,它会选择正确的视图,并且视图不会意识到这样的逻辑:

public ActionResult View(int id)
{
    if (HasUserEditingPrivileges)
        return View("Edit", new MyModel(id));

    return Redirect("UnauthorizedAccess"); // Oops, something went wrong
}

为什么不呢?

  • 因为视图不应该知道这样的逻辑。如果您需要类似的东西(CGI 之类的顺序流),那么您不应该使用 MVC,因为它会增加您不需要的复杂性。
  • 因为你不能(除非有人发现了一个可怕的肮脏的hacky技巧)。 MVC 的结构是在必须显示页面时构建页面(控制器决定哪个页面和哪些数据)。当这个建筑开始时,需要输出(除非你抛出一个异常来表示错误,但你真的应该避免异常来处理程序流......)。对于小的 if,您可以简单地使用第一个提到的方法。

总结一下:

在 ASP.NET-MVC Razor 视图中,中止呈现视图/部分视图的正确方法是什么?

没有正确的方法,因为你不能这样做。视图中的代码必须呈现页面,它不必决定应该将哪个页面发送给客户端。如果您正在做其他事情,那么您就是using MVC as it shouldn't be used,这是不正确的。

【讨论】:

  • 我同意你提到的一切。而且几乎总是这样编码。但有时我想做我上面描述的事情。不过我是 +1 你,因为我原则上同意你所写的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多