为啥 Razor Pages 是在 Asp.net Core 中创建 Web UI 的推荐方法?

Posted

技术标签:

【中文标题】为啥 Razor Pages 是在 Asp.net Core 中创建 Web UI 的推荐方法?【英文标题】:Why is Razor Pages the recommended approach to create a Web UI in Asp.net Core?为什么 Razor Pages 是在 Asp.net Core 中创建 Web UI 的推荐方法? 【发布时间】:2018-03-28 09:26:08 【问题描述】:

学习新事物需要时间、空间和精力的投入。我目前正在学习 Asp.Net Core MVC 2.0。这个ASP.NET Core tutorials overview 声明:

Razor Pages 是使用 ASP.NET Core 创建 Web UI 的推荐方法

这些信息让我在决定是否必须停止学习 Asp.net Core MVC 并开始学习 Asp.net Core Razor Pages 时感到困惑。

为什么推荐使用 Razor 页面在 Asp.net Core 中创建 Web UI?

欢迎任何方向。

【问题讨论】:

我建议先学习更传统的 .net core MVC,然后再学习 RazorPages。通过这种方式,您最终会更好地全面了解这些技术。 我会推荐使用 MVC 而不是 Razor Pages。从长远来看,你会过得更好。 我建议您将 ASP.NET Core 用于您的 API,并使用与您的“中间层”技术完全分离的前端技术,例如 Angular 或 ReactJs 他们似乎删除了“推荐”声明。 @EKanadily:是的。谢谢!他们可能已经撤销了该声明。 :-) 【参考方案1】:

来自微软文档中的this 文章:

MVC:使用控制器和视图,应用程序通常具有非常 大型控制器,可以处理许多不同的依赖项和视图模型并返回许多 不同的看法。这导致了很多复杂性,并且经常导致控制器不遵循 Single Responsibility PrincipleOpen/Closed Principles 有效。

Razor Pages 解决了这个问题 通过在 Web 应用程序中封装给定逻辑“页面”的服务器端逻辑来发布。没有服务器端逻辑的 Razor 页面可以只包含一个 Razor 文件(例如“Index.cshtml”)。但是,大多数重要的 Razor 页面将具有关联的页面模型 类,按照惯例,它与带有“.cs”扩展名的 Razor 文件命名相同(例如,“Index.cshtml.cs”)。这个页面模型类结合了 Controller 和 ViewModel 的职责。不是使用控制器操作方法处理请求,而是像“OnGet()”这样的页面模型处理程序 执行,默认呈现其关联页面。

Razor 页面简化了构建过程 ASP.NET Core 应用程序中的单个页面,同时仍提供 ASP.NET Core MVC 的所有架构功能。对于新的基于页面的功能,它们是一个很好的默认选择。

何时使用 MVC

如果您正在构建 Web API,则 MVC 模式比尝试使用 Razor 页面更有意义。 如果您的项目将只公开 Web API 端点,您最好从 Web API 项目开始 模板,否则很容易将控制器和关联的 API 端点添加到任何 ASP.NET Core 应用程序。如果要迁移现有应用程序,还应该使用基于视图的 MVC 方法 从 ASP.NET MVC 5 或更早版本到 ASP.NET Core MVC,并且您希望使用最少的 努力。完成初始迁移后,您可以评估采用是否有意义 用于新功能的 Razor 页面,甚至作为批发迁移。

注意: 无论您选择使用 Razor Pages 还是 MVC 视图构建 Web 应用程序,您的应用程序都将具有 类似的性能,并将包括对依赖注入、过滤器、模型绑定、验证等的支持。


更新:我在this github 问题上阅读的更多原因scott sauber 评论:

我们将 Razor 页面用于 [复杂] 健康保险门户...我们有 60 多个页面,我可以说对于服务器渲染的 HTML,我永远不会回到 MVC。它也不仅仅是简单的事情。健康保险领域本质上是复杂的,并将其与它是一个多租户应用程序(我们将产品出售给其他保险公司)这一事实相结合,这增加了更多的复杂性,因为该应用程序是高度可配置的,因为不同的保险公司做事略有不同.

为什么要使用它?

Razor 页面默认更安全。 Razor 页面默认为您提供 AntiForgeryToken 验证。此外,您还可以通过 [BindProperty] 选择加入模型绑定的属性,从而限制您遭受过度发布攻击。

默认情况下,Razor Pages 具有更好的文件夹结构,可以更好地扩展。在 MVC 中,默认文件夹结构根本无法扩展。当所有三个最终紧密耦合时,为视图、控制器和通常的视图模型拥有单独的文件夹是一个巨大的 PITA 工作。您最终会跳到所有 3 个文件夹并在需要添加或更改功能的任何时候导航一堆。这太糟糕了。这就是我提倡功能文件夹的原因。使用 Razor Pages,您的 PageModel (Controller + ViewModel) 与您的视图位于同一文件夹中。您只需按 F7 即可在它们之间切换,也非常方便。

导致代码更易于维护,扩展性更好。 使用 MVC,让具有 10 多个操作的控制器变得臃肿非常容易。通常,这些操作甚至没有以任何方式相互关联(可能除了两者之间的重定向)。这使得导航控制器以查找代码变得非常困难。如果 Controller 中也有私有方法,情况会变得更糟,进一步增加了方法膨胀。使用 Razor 页面,几乎不可能使用与页面无关的方法来膨胀页面模型。您放入 PageModel 的所有内容都与您的 Page 相关。

单元测试更容易。使用控制器,您可能有 8 个操作,并且您注入的一些依赖项仅与一两个操作相关。因此,当对单个 Action 进行单元测试时,您要么需要对它们进行不必要的模拟,要么传递一个 null,这两者都感觉很糟糕(这可以通过 Builder 模式稍微解决)。使用 Razor Pages,您注入的依赖项 100% 与您正在使用的 GET 和 POST 操作相关。感觉很自然。

路由更容易。默认情况下,在 Razor Pages 中,路由只匹配您的文件夹结构。这使得嵌套文件夹更容易完成。例如,我们所有的 HR Admin 页面都在 /Administrator 文件夹下,所有 Employee 页面都在 /Employee 文件夹下。我们可以授权整个文件夹,并说此人必须是管理员才能访问/Administrator 的任何子文件夹,这比使用多个构成管理员功能的控制器要容易得多。

我认为这是大事。


更新 2:

这是关于 MVC 模式的一些复杂性,不能直接回答这个问题,但可能很有用:Facebook 的一位工程经理说 (here) 他们“足够”的大型代码库和大型组织,“ MVC 很快就变得非常复杂,” 得出的结论是 MVC 无法扩展。每次他们尝试添加新功能时,系统的复杂性都会呈指数级增长,从而使代码“脆弱且不可预测”。对于刚接触某个代码库的开发人员来说,这已成为一个严重的问题,因为他们害怕接触代码,以免破坏某些东西。结果是 MVC 在 Facebook 中分崩离析

【讨论】:

如果Asp.Net Core Razor PagesASP.NET Core MVC 好,为什么Microsoft 会发布ASP.NET Core MVC?看来大家here 喜欢MVC 风格,请指导我们何时应该使用ASP.NET Core MVC @stom Razor Pages 只是一种构建 Web 应用程序的新方法(您现在在框中有一个新工具或新选项)。正如When to use MVC 部分所写:如果您想定义/使用 Web API,MVC 模式更有意义。此外,当您将现有应用程序从 MVC 5 或更早版本迁移到 ASP.NET Core 时,它​​也很有用。另请注意,MVC 和 Razor 页面可以在同一个项目中同时使用。 我们从 Web 应用程序的 Razor 页面开始,就知道我们将来不会有移动应用程序/API。但是如果我们这样做,我猜这个解决方案会有 MVC WebAPI 吗?那正确吗?那么会有 2 个单独的解决方案吗? @dcpartners 你的移动应用是什么?对于 WebAPI,您可以将它与 Razor Pages 混合在同一个项目中。无需成为单独的解决方案或项目。【参考方案2】:

Razor 页面针对基于页面的工作流程进行了优化,并且可以在这些场景中使用,其移动部件比传统 MVC 模型少。这是因为您不需要处理控制器、操作、路由、视图模型和视图(就像您通常那样)。相反,您的路线是基于约定的,并且您的 PageModel 可作为您的 Controller、Action(s) 和 ViewModel 合而为一。当然,页面取代了视图。您也不必像在 MVC 中那样拥有那么多文件夹,从而进一步简化您的项目。

来自ASP.NET Core - Simpler ASP.NET MVC Apps with Razor Pages,Steve Smith 于 2017 年 9 月发表的 MSDN 文章:

[Razor Pages] 提供

一种在 ASP.NET Core 应用程序中组织代码的更简单方法,使实现逻辑和视图模型更接近视图实现代码。 它们还提供了一种更简单的方式来开始开发 ASP.NET Core 应用程序,

那篇文章提供了有关为什么将 Razor Pages over MVC 用于基于页面的工作流的更多信息。显然,对于 API,您仍然希望使用控制器。

第 3 方编辑 - 经典 MVC 文件夹组织的缺点

ASP.NET Core - Feature Slices for ASP.NET Core MVC 是 2016 年 9 月的一篇较早的 MSDN 文章,描述了为什么用于组织视图和控制器的经典 MVC 约定可能对大型项目不利。本文给出了四个松散相关的应用程序概念的示例:忍者、植物、海盗和僵尸。本文概述了一种在默认文件夹约定之外构建它们的方法,方法是按功能或责任区域将文件组织到文件夹中。

【讨论】:

Razor 页面是否像 MVC 一样可测试? 是的,他们是。它们同样可测试。 作为解耦和关注点分离的粉丝,我必须问,如果 PageModel 作为 Controller、Action(s) 和 Viewmodel 工作,那么这一层似乎根本不能重用,是吗? ?如果我理解正确,从长远来看,我们将很难过。从维护的角度来看,它也很糟糕,我不愿意调试您提供的示例中的视图: 图 8 New.cshtml — 添加新工厂。这种模式对我来说看起来很糟糕,我宁愿随时使用 MVC。 控制器只是动作的容器; Action 只是一个处理请求的方法; ViewModel 是理想情况下特定于一个 View 的 DTO。在传统的 MVC 或 Razor Pages 方法中,这些都不是特别可重用的。调试体验没有区别,尽管我承认我通常不会调试视图,因为我没有在其中添加逻辑。如果您愿意,欢迎您继续使用 MVC,或者混合搭配。继续支持这两种方法。 关于可测试性:您可能认为 RP 更容易测试,因为您不需要模拟未使用的依赖项。当对单个 Action 进行单元测试时,必须模拟依赖项或将其作为 null 传入。使用 Razor Pages,您注入的依赖项与 PageModel 中的 GET、POST、PUT 等操作 100% 相关。【参考方案3】:

Microsoft 正在回归 WebForms 方法以简化项目结构,相信“约定优于配置”的口头禅,同时向开发人员隐藏配置以加快速度。但它的缺点是一切都会再次混合。这看起来不像是组织的明智之举。但是……嘿!新事物必须引起开发人员对 Microsoft 的注意。

如果您的页面使用 RESTful 的 MVC Web API,那么仅使用 Razor 页面确实更容易。如果没有,我建议您使用 Core MVC。

在大型项目中,模型和控制器一起在同一个文件中,维护将是一场噩梦。它适用于只有 2 个属性长的类,但它违反了 OOP 的打开关闭原则。您应该设计和使用可以随时间增长(可扩展)并且仍然稳定且符合逻辑的架构(无需重新构建项目),只需使用相同的模式进行扩展即可。

【讨论】:

关于“回到 WebForms”的意义重大。它就像 Web 表单。我认为使用 MVC 我们可以摆脱这种情况。这是没有设计器的 Web 表单!旧的就是新的。 > 相信“约定优于配置”的口头禅是错误的。 RP 与 MVC 一样可配置。与 MVC 相比,情况如何更复杂? > 在大型项目中,模型和控制器放在同一个文件中,维护将是一场噩梦。又错了。基于什么,而不是你的经验。 >但它违反了OOP的Open Close Principle。 - 也不正确【参考方案4】:

作为一名软件架构师,我会自动使用设计模式。我最喜欢的是 Facade 设计模式。您将与 Home 相关的所有内容隐藏在 HomeController 后面,并且您可以对 Repositories 执行相同操作。

想知道一件有趣的事吗?一位导游解释了名字在哪里 门面来自。在阿姆斯特丹,你有横跨水域的大房子。 从外面看,它们看起来很奢华。但从背后他们可以 杂乱。房子的正面隐藏着它背后的东西。设计模式 来自建筑世界。好吧,我的应用程序落后了 看起来也不错,但很高兴从导游那里知道 解释。

如何支持 Razor 页面中的共享分组操作。如果您查看 MVC 控制器,您会发现您可以根据功能对控制器操作进行分组。你可以说主页就是这样一个功能。然后你有一个 HomeController,其中包含 About() 和 Contact(),但对于 Razor Pages,这将是不同的页面。可能你有一个很大的 HomeController,里面有 5 个其他视图。它们都可以分组在同一个 HomeController 中。

控制器有两个 Razor 页面没有的东西:

    共享:您可以在不同页面之间共享控制器动作,有时控制器动作不仅绑定到一个页面,还可以在多个页面之间共享。请记住,控制器操作也只能返回数据(JSON/XML/等)。有时他们返回的内容也可以被不同的页面使用。 分组:您可以将相关的 Controller 操作分组到一个 Controller 中。好吧,如果你是小型控制器文件的粉丝,你不会这样做。我愿意。我根据功能对控制器进行分组。这让导航变得更加容易。

Razor 页面的处理方式是什么:我认为目录的使用:

分组:如果我们有 HomeController,那么我们可以创建一个子目录 Home,其中包含所有主页。

问题:对于一个简单的 Home 就足够了。但是假设我们有一个 XController 用于所有操作同一个存储库。您可以在 XController 的 Initializer 函数中初始化该存储库。但是对于 X 子目录中的页面,您必须再次对所有 X 操作执行此操作。那是干的吗?

共享:您可以创建一个“共享”子目录,并在其下创建具有应在页面之间共享的功能的目录。

问题:如果您查看我的修复程序,您会发现我使用目录来解决 Razor 页面的共享和分组问题。

你会怎么做?

或者...是否 Razor 页面仅适用于简单的网站,这可能是此版本 Razor 页面的结论。

【讨论】:

不知道微软为什么推荐 Razor Pages。除此之外,很容易看出微软在倾听客户的声音。客户想要像 RoR 这样的 MVC,所以他们得到了它。然后他们想要像 Java 这样的跨平台,所以他们得到了它。然后他们想要 MVVM,并以 Razor Pages 的形式得到了它。根据您的需要在 MVC 和 MVVM 之间进行选择。他们都在这里留下来。 留下来?纳德拉的视野没有那么宽。他们砍了很多。与 Blazor 相同,您是否应该投资它。我现在看不到微软对他们提供的技术的任何承诺。【参考方案5】:

Blazor 服务器的架构很奇怪。它看起来像一个使用 SignalR 的聊天应用程序。我对此类应用程序的经验是,事件可能会丢失。我不想丢失事件,更好的是它们被堆叠并保证像邮件一样被处理。

【讨论】:

【参考方案6】:

2013 年,开发人员在论坛上询问“Microsoft 是什么意思,Silverlight 不是推荐的……???” 只是这一次,MVC 将被宣布为死亡和万岁的 MVVM。 您可能会期望 MVC 会慢慢地被扔到废品堆中,但从现在起大约 18 个月后会加速,并且您花在学习 MVC 上的所有时间都将被扔到同一个废品堆中。 此外,MVVM 看起来很简单,但需要一年的时间才能掌握并真正做到正确。

【讨论】:

现在,18 个月后,MVC 仍然生机勃勃,蓬勃发展。加入持久性后,否定是很难的。 我不是在谈论 MVC,我是在谈论 Razor 页面。 Razor 页面使用代码隐藏,MVC 使用控制器。我只是在其中构建了一个包含 MVC 和 MVVM 的应用程序。它是多层的,所以使用 MVC 或 MVVM 完全没有问题。我不喜欢在目录中分组但想知道是否无法在代码中解决的 Razor 页面的问题。 @Daniel 学习技术没有问题。我是一名全栈开发人员,也了解 Angular,我猜它很糟糕 :-) Silverlight 存在于 XAML 领域,因此对它的投资可用于 WPF 和 UWP 应用程序。

以上是关于为啥 Razor Pages 是在 Asp.net Core 中创建 Web UI 的推荐方法?的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Web Pages - 添加 Razor 代码

Asp.net core razor pages 加载部分页面

ASP.NET Razor Pages 路由参数命名页面

结合 Razor Pages 和 ApiControllers 的应用程序中的 Asp.net 核心异常处理

部分视图中的模型为空 - asp.net core razor pages

ASP.NET Razor Pages JavaScript 文件返回未定义的错误