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

83

学习新知识需要投入时间、空间和精力。我目前正在学习Asp.Net Core MVC 2.0。这篇ASP.NET Core教程总览中指出:

Razor Pages 是使用 ASP.NET Core 创建 Web 用户界面的推荐方法。

对于我来说,这些信息让我困惑了,不知道是应该停止学习Asp.net Core MVC然后开始学习Asp.net Core Razor Pages。

  • 为什么Razor Pages在Asp.net Core中是创建Web用户界面的推荐方法?

欢迎提供任何指导。


7
我建议先学习更传统的.NET Core MVC,然后再学习Razor Pages。这样做可以让你对这些技术有一个更全面的理解。 - nurdyguy
3
我建议您使用ASP.NET Core来创建API,并选择与"中间层"技术完全解耦的前端技术,例如Angular或ReactJs。 - Brian Ogden
6
他们似乎已经删除了“推荐”的声明。 - EKanadily
1
@Ekanadily - 没有被撤销,只是移动了位置:https://learn.microsoft.com/en-us/aspnet/core/fundamentals/choose-aspnet-framework?view=aspnetcore-2.2#framework-selection - James H
简直不敢相信我竟然被骗用 Razor Pages 做项目了。这是什么烂货,它怎么比 MVC 更好呢? - Scott Wilson
显示剩余3条评论
6个回答

86

这篇Microsoft文档中:

MVC:使用控制器和视图,应用程序通常具有非常庞大的控制器,处理许多不同的依赖关系和视图模型,并返回许多不同的视图。这导致了很多复杂性,并经常导致控制器没有有效地遵循单一职责原则开闭原则

Razor Pages解决了这个问题,通过封装给定逻辑“页面”的服务器端逻辑,在Web应用程序中。一个没有服务器端逻辑的Razor Page可以简单地由一个Razor文件(例如“Index.cshtml”)组成。然而,大多数非平凡的Razor Pages都会有一个相关的页面模型类,按照惯例,它的名称与带有“.cs”扩展名的Razor文件相同(例如,“Index.cshtml.cs”)。这个页面模型类结合了Controller和ViewModel的职责。页面模型处理程序像“OnGet()”一样处理请求,通过默认渲染其关联页面来执行。

Razor Pages简化了在ASP.NET Core应用程序中构建单个页面的过程,同时仍然提供了所有ASP.NET Core MVC的架构特性。它们是新页面功能的良好默认选择。

何时使用MVC

如果你正在构建Web API,MVC模式比尝试使用Razor Pages更有意义。如果你的项目只会暴露Web API端点,你应该从Web API项目模板开始,但是对于任何ASP.NET Core应用程序来说,添加控制器和相关的API端点也很容易。如果你正在将现有应用程序从ASP.NET MVC 5或更早版本迁移到ASP.NET Core MVC,并且希望付出最少的努力,那么你还应该使用基于视图的MVC方法。一旦完成了初始迁移,你可以评估是否有必要采用Razor Pages作为新功能甚至整体迁移。
注意:无论你选择使用Razor Pages还是MVC视图构建Web应用程序,你的应用程序将具有类似的性能,并包括依赖注入、过滤器、模型绑定、验证等支持。

更新:我在这个GitHub问题上读到了一些由Scott Sauber评论的原因:

我们正在为一个[复杂的]医疗保险门户网站使用Razor Pages...我们有60多个页面,我可以说对于服务器呈现的HTML,我永远不会回到MVC。这也不仅仅是为了简单的事情。健康保险领域本质上是复杂的,再加上它是一个多租户应用程序(我们将产品销售给其他保险公司),这增加了更多的复杂性,因为不同的保险公司会以稍微不同的方式处理事情。

为什么使用它?

  • Razor Pages更加安全。 Razor Pages默认提供AntiForgeryToken验证。此外,您可以通过[BindProperty]选择要绑定到模型的属性,从而限制了过度发布攻击的风险。

  • Razor Pages具有更好的文件夹结构,可扩展性更强。 在MVC中,默认的文件夹结构不具备扩展性。将视图、控制器和ViewModel分别放在不同的文件夹中,尽管这三个元素最终紧密耦合,但是工作起来非常麻烦。每次需要添加或更改功能时,都需要在这3个文件夹之间跳转和导航,这是非常糟糕的。这就是为什么我提倡使用“特征文件夹”。对于Razor Pages,您的PageModel(Controller + ViewModel)与View位于同一文件夹中。您只需按F7键在它们之间切换,这也非常方便。

  • 代码更易于维护,具有更好的可扩展性。 在MVC中,很容易让控制器膨胀到10个以上的操作。通常,这些操作彼此之间没有任何关系(除了可能在两者之间重定向)。这使得在控制器中查找代码变得非常困难。如果控制器中还有私有方法,情况就更糟了,这进一步增加了方法的膨胀。使用Razor Pages,几乎不可能用与页面无关的方法使您的Page Model膨胀。您在PageModel中放置的所有内容都与您的Page相关。

  • 单元测试更容易。 对于控制器,您可能有8个操作,并且注入的某些依赖关系仅与其中一个或两个操作相关。因此,在单元测试单个操作时,您需要不必要地模拟它们或传递null,这两种情况都感觉很恶心(可以使用Builder模式解决这个问题)。对于Razor Pages,您注入的依赖关系100%与您正在处理的GET和POST操作相关。这感觉非常自然。

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

我认为那就是重点。


更新2:

这篇文章讨论了MVC模式的一些复杂性,虽然没有直接回答问题,但可能会有用:Facebook的一位工程经理(在这里)表示,对于他们“足够”大的代码库和庞大的组织来说,“MVC变得非常复杂,非常快速”,最终得出结论MVC不具备可扩展性。每次尝试添加新功能时,系统的复杂性呈指数级增长,使代码变得“脆弱和不可预测”。这对于某个代码库的新开发人员来说成为了一个严重的问题,因为他们害怕触及代码,以免破坏某些东西。结果是MVC在Facebook上分崩离析

enter image description here


如果 Asp.Net Core Razor PagesASP.NET Core MVC 更好,那么为什么 Microsoft 还发布了 ASP.NET Core MVC?看起来这里的人们更喜欢 MVC 风格,请指导我们何时应该使用 ASP.NET Core MVC - Shaiju T
6
@stom Razor Pages是一种构建Web应用程序的新方法(现在您有一个新工具或选择)。正如“何时使用MVC”部分所述:如果您想定义/使用Web API,则MVC模式更有意义。此外,当您将现有应用从MVC 5或更早版本迁移到ASP.NET Core时,它也很有用。还请注意,MVC和Razor Pages可以同时在同一个项目中使用。 - S.Serpooshan
我们开始使用 Razor Pages 来开发我们的 Web 应用程序,明知道未来不会有移动应用程序/API。但是如果我们需要,我猜解决方案将会使用 MVC WebAPI,对吗?那么就会有两个单独的解决方案了吗? - dcpartners
@dcpartners,你们的移动应用是什么?对于WebAPI,你可以将其与Razor Pages混合在同一个项目中。不需要单独的解决方案或项目。 - S.Serpooshan

50
Razor Pages是针对基于页面的工作流程进行优化的,与传统的MVC模型相比,可以少用许多组件。这是因为您不需要处理控制器、操作、路由、视图模型和视图(通常情况下需要)。相反,您的路由是基于约定的,PageModel充当您的控制器、操作和视图模型。当然,页面替换了视图。您还不需要像在MVC中那样拥有太多文件夹,从而进一步简化了项目。
来自ASP.NET Core - Simpler ASP.NET MVC Apps with Razor Pages的MSDN文章,作者为Steve Smith,时间为2017年9月:

[Razor Pages]提供了一种更简单的方式来组织ASP.NET Core应用程序中的代码,使实现逻辑和视图模型更接近于视图实现代码。

  • 它们还提供了一种更简单的方法来开始开发ASP.NET Core应用程序。
  • 该文章有更多关于为什么要使用Razor Pages而不是MVC进行基于页面的工作流程的信息。显然,对于API,您仍然需要使用控制器。

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

    ASP.NET Core - Feature Slices for ASP.NET Core MVC,这是一篇较早的MSDN文章,发布于2016年9月,介绍了为什么传统的MVC约定组织视图和控制器可能对大型项目有不利影响。该文章举例说明了四个松散相关的应用程序概念:Ninjas,Plants,Pirates和Zombies。该文章概述了一种通过按特性或责任区域将文件组织成文件夹来结构化它们的方式,而不是使用默认的文件夹约定。


    Razor页面和MVC一样可测试吗? - Troy Turley
    2
    是的,它们是一样可测试的。 - ssmith
    2
    作为一个关注解耦和关注点分离的粉丝,我必须问一下,如果PageModel作为控制器、操作和视图模型,那么这个层似乎根本不可重用,是吗?如果我理解正确,从长远来看,我们会遇到很大的问题。从维护的角度来看,这也非常糟糕,我不想调试像你提供的例子中的视图:Figure 8 New.cshtml-添加新植物。这种模式对我来说看起来很糟糕,我宁愿随时使用MVC。 - Héctor Álvarez
    9
    控制器仅是操作的容器,操作是处理请求的方法;视图模型是特定于一个视图的数据传输对象。在传统 MVC 或 Razor Pages 方法中,这些元素都不是特别可重用的。虽然我承认我通常不会在视图中放置逻辑,所以在调试体验方面没有区别。如果您喜欢使用 MVC 或混合使用,两种方法都将继续受到支持。 - ssmith
    1
    关于可测试性:你可以认为RP更容易进行测试,因为你不需要模拟未使用的依赖项。当单元测试一个单一的Action时,必须将依赖项模拟或传递为空。对于Razor Pages,你注入的依赖项与PageModel中的GET、POST、PUT等操作是100%相关的。 - RickAndMSFT
    @RickAndMSFT,如果Asp.Net Core Razor PagesASP.NET Core MVC更好,那么为什么Microsoft还发布了ASP.NET Core MVC?看起来这里的人们喜欢MVC风格,另外这个待办工作完成了吗?请指导我们何时应该使用ASP.NET Core MVC - Shaiju T

    9

    微软正在重新采用WebForms方法简化项目结构,信任“约定优于配置”口号,同时将配置从开发人员隐藏起来,以加快速度。但这样做的缺点是所有内容将再次混合在一起。这看起来不是一个组织得很好的聪明举动。但是...嘿!某些新东西必须吸引开发者对微软的关注。

    如果您的页面使用MVC Web API进行RESTful操作,那么使用Razor页面确实更容易。否则,我建议使用Core MVC。

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


    1
    关于“回到WebForms”的观点非常好。这就像Web Forms一样。我以为通过MVC,我们正在远离它。这是没有设计师的Web Forms!新的就是旧的。 - CoderSteve
    3
    相信“约定优于配置”的口号是错误的。RP和MVC一样可配置。事情比MVC更混乱吗? 在大型项目中,模型和控制器在同一个文件中,维护将是一场噩梦。再次错误。基于什么,不是你的经验。 但它违反了OOP的开闭原则。- 也不正确。 - RickAndMSFT

    3
    作为软件架构师,我会自动使用设计模式。我非常喜欢Facade设计模式。您可以将与Home相关的所有内容都隐藏在HomeController后面,并且您也可以对存储库执行相同的操作。
    想知道一个有趣的事情吗?一位导游解释了Facade名称的由来。在阿姆斯特丹,你会看到河对岸高大的房子。从外面看起来很豪华,但从后面看却可能会很乱。房子的正面掩盖了其背面。设计模式来自建筑界。我的应用程序中的背面看起来也不错,但是从导游那里了解解释的原因还是很好的。
    那么,在Razor页面中支持共享和分组操作呢?如果您查看MVC控制器,则可以基于功能对控制器操作进行分组。您可以说首页就是这样一种功能。然后,您会有一个具有About()和Contact()的HomeController,但是在Razor Pages中,这将是不同的页面。也许您有一个具有5个其他视图的大HomeController。它们可以全部分组在同一个HomeController中。
    控制器拥有两个Razor Pages没有的东西:
    1. 共享:您可以在不同的页面之间共享控制器操作,有时控制器操作并不仅限于一个页面,而是可以在多个页面之间共享。请记住,控制器操作有时仅返回数据(JSON/XML等)。它们返回的内容有时也可以被不同的页面使用。
    2. 分组:您可以将相关的控制器操作组合在一个控制器中。如果您喜欢小型控制器文件,则不会这样做。我会这样做。我根据功能对我的控制器进行分组。这使得导航更加容易。
    Razor Pages处理这个问题的方法是:使用目录:
    1. 分组:如果我们有HomeController,那么我们可以创建一个名为Home的子目录,并在其中放置所有的Home页面。
    2. 共享:您可以创建一个“Share”子目录,并在其中放置应该在页面之间共享的功能目录。
    这里有一个问题:对于简单的Home来说这已经足够了。但是,假设我们有一个使用相同存储库的XController。您可以在XController的初始化函数中初始化该存储库。但是对于X子目录中的页面,您需要再次执行所有X操作。这是否符合DRY原则?
    如果您看一下我的修复,您就可以看到我使用目录来解决Razor页面的共享和分组问题。
    那么您如何做呢?或者说,Razor Pages只适用于简单的网站吗?这可能是此版本的Razor Pages的结论。

    不确定为什么微软推荐Razor Pages。除此之外,很容易看出微软在倾听客户的声音。客户想要像RoR一样的MVC,所以他们得到了它。然后他们想要像Java一样的跨平台,所以他们得到了它。然后他们想要MVVM,而他们通过Razor Pages实现了它。根据您的需求选择MVC和MVVM。它们都将继续存在。 - Denny Jacob
    留下来吗?纳德拉的视野并不那么开阔。他们砍掉了很多东西。Blazor也是如此,你应该投资吗?我现在看不到微软对他们提供的技术有任何承诺。 - Herman Van Der Blom

    0

    Blazor server 有一个奇怪的架构。它使用 SignalR,看起来像一个聊天应用程序。我对这样的应用程序的经验是事件可能会丢失。我不想丢失事件,最好的方式是将它们堆叠起来,并保证像邮件一样被处理。


    -4

    2013年,开发人员在论坛上问道:“微软的意思是什么,Silverlight不被推荐使用...???” 现在,MVC将被宣布死亡,MVVM将长存。 你可以预计,在大约18个月后,MVC将被逐渐淘汰,而你所花费的时间学习MVC也将被抛弃。 此外,MVVM看起来很简单,但需要一年的时间才能掌握并真正做到正确。


    我不是在谈论MVC,而是在谈论Razor页面。 Razor页面使用代码后台,MVC使用控制器。 我刚刚构建了一个同时包含MVC和MVVM的应用程序。它是多层的,因此在使用MVC或MVVM时没有任何问题。 我对Razor页面的问题在于我不喜欢目录中的分组,但想知道是否可以通过代码解决。@Daniel学习技术没有问题。我是一名全栈开发人员,也知道Angular,猜猜它有多糟糕 :-) Silverlight在XAML的领域中仍然存在,因此对其的投资可以用于WPF和UWP应用程序。 - Herman Van Der Blom

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接