【问题标题】:Partial Pages in ASP.NET Core 2.0ASP.NET Core 2.0 中的部分页面
【发布时间】:2018-01-26 09:13:48
【问题描述】:

TL; DR 在 ASP.NET Core 2.0 中是否可以使用“部分页面”?如果是这样,为什么我会收到下面描述的错误?

我一直在搞乱 ASP.NET 2.0 的新 Razor Page 功能,并且在处理部分问题时遇到了一些麻烦。上面链接的文档在几个地方都提到了“部分”,但仅限于说一些神秘的东西,例如“您与 MVC 控制器和传统 Razor 视图一起使用的布局、模板和部分正常工作。”它们是指partial Views,就像我们习惯的那样,还是某种新的部分页面?他们表明,名称中带有常规Partial 后缀的文件可以放在Pages/ 文件夹中,但他们提到的文件(例如_ValidationScriptsPartial.cshtml)没有@page 声明。如果“部分页面”确实是一个新事物,那么我希望以下最小场景可以工作:

  • 一个名为Derp.cshtml的页面文件:

    @page
    @namespace MyApp.Pages
    @model DerpModel
    
    <p>Member 1: @Model.Member1</p>
    <p>Member 2: @Model.Member2</p>
    
  • 同一目录下名为Derp.cshtml.cs的类文件(嵌套在VS 2017的解决方案资源管理器中的第一个下),包含以下类:

    namespace MyApp.Pages {  
        public class DerpModel : PageModel {
            public void OnGet() {
                Member1 = "Derp Member1";
                Member2 = "Derp Member2";
            }
    
            public string Member1 { get; set; }
            public string Member2 { get; set; }
        }
    }
    
  • 同一目录下的第二个Page文件DerpWrapper.cshtml,代码如下:

    @page "{id}"
    @namespace MyApp.Pages
    @model DerpModel
    
    <p>Outer Member 1: @Model.Member1</p>
    <p>Outer Member 2: @Model.Member2</p>
    @Html.Partial("Derp", Model)
    
  • 当然还有一个声明@namespace MyApp.Pages_ViewImports文件

请注意,两个 Razor 页面具有相同的 @model 类型,第二个页面基本上通过调用 Html.Partial() 来结束第一个页面并传递其 Model。这应该都是非常标准的东西,但是在导航到 http://localhost:xxx/DerpWrapper 时,由于带有以下堆栈跟踪的 NullReferenceException,我得到了 500 响应。

    MyApp.Pages.Derp_Page.get_Model()
    MyApp.Pages.Derp_Page+<ExecuteAsync>d__0.MoveNext() in Derp.cshtml
    +
    <p>Inner Member1: @Model.Member1</p>
    ...
    MyApp.Pages.DerpWrapper_Page+<ExecuteAsync>d__0.MoveNext() in DerpWrapper.cshtml
    +
    @Html.Partial("Derp", Model)
    ...

为什么“包装”页面的Model 等于 null?有没有办法定义一个 Razor 页面并使用 Html.Partial() 从另一个页面或视图显示它?

【问题讨论】:

  • 我对 ASP.NET Core 不是很熟悉,但是新的 @page 指令不会导致页面表现为操作吗?这将暗示必须使用子动作而不是.Partial 来嵌入它,但谁知道呢。无论如何,我只是尝试从部分 Derp.cshtml 中删除 @page
  • 剃须刀页面部分在此处描述learnrazorpages.com/razor-pages/partial-pages 省略部分的@page 将解决 nullrefex

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


【解决方案1】:

Razor’s partial views 基本上是.cshtml 视图,它们被嵌入到另一个视图中,即剃刀视图或剃刀页面。它们在视图呈现,因此继承了视图的一些属性,例如它的ViewData。但是,它们没有控制器、页面模型或某种其他类型的“代码隐藏”,可以让您运行部分代码。

因此,partials 的主要用途是将自身不包含逻辑的公共组件提取到单独且可重用的文件中。

Razor 中存在的另一种可重用组件是view components。视图组件类似于局部组件,但它们确实有一个支持它们的实际类,并且允许您将自己的逻辑添加到视图组件中。

目前,视图组件遵循视图的 MVC 布局,这意味着视图组件实际上是一个类,并且您从其 Invoke 方法返回一个视图,这导致视图引擎在 @987654327 中找到该 .cshtml @ 文件夹。不过,David Fowler 向我证实,他们也在为视图组件开发类似 Razor 页面的体验,因此在更高版本的 ASP.NET Core 中,您最终将能够编写 .cshtml 视图组件并添加一些代码- 在它后面(就像 Razor 页面一样)。

回到您的问题,目前 MVC 路由有两种入口点:MVC 控制器(可能返回视图)和 Razor 页面。但是,它们中的任何一个都不能调用它们内部的一个或另一个。如果您正在渲染视图,则可以加载部分视图或视图组件,但不能加载其他“完整”视图或 Razor 页面。如果您正在渲染 Razor 页面,您还可以加载部分或查看组件,但仍然没有其他“完整”视图或 Razor 页面。

所以你想做的事情根本不可能,因为 Razor 页面应该是路由的入口点,并且在调用任何视图作为局部视图时(在某些情况下)可能工作,你肯定不会得到该视图的控制器或为其运行的页面模型。如果你想调用具有复杂逻辑的东西,你应该使用视图组件。

【讨论】:

  • 感谢您的详细回复!我肯定需要阅读更多关于 ViewComponents 的内容,这些可能是我正在寻找的。在我的项目中混合部分视图和页面似乎很奇怪。并且 +1 与 Microsoft 开发人员串通一气!
【解决方案2】:

有关堆栈溢出的答案会保留很长时间,因此我们必须确保它们得到改进。

添加到 Poke 的答案中或更确切地说是更正它。部分视图将页面之间的公共部分分开。 这些部分可以包含逻辑。但该逻辑不应涉及任何特定页面中包含或定义的任何字段(变量或对象)。他们可以通过依赖注入来应用逻辑......通过将它们注入到局部视图中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-14
    • 2018-12-24
    • 2018-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多