为啥 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 Principle
或 Open/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 Pages
比ASP.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 加载部分页面
结合 Razor Pages 和 ApiControllers 的应用程序中的 Asp.net 核心异常处理