我如何 conditionally/dynamically 在 Asp.Net Core Razor 页面中包含 Razor 子页面?

How do I conditionally/dynamically include Razor subpages in an Asp.Net Core Razor page?

此处 Asp.Net Core/Razor 的新手。

我正在构建一个 Asp.Net Core Razor 页面。 我有一个主要的 Razor 页面作为父页面。 我有一个子页面集合(超过 20 种不同的子页面类型)。

我希望能够有条件地包含一个子页面 基于我父页面视图模型中的标识符。

我的父级 Razor 页面的基本简化版本看起来像这样:

@model DocumentsViewModel

<div>
<!-- Some basic common form functionality--!>
</div>

<div class="WhereToEmbedChildForm">
        @Html.Partial("SomeChildViewName")

        @{ Html.RenderPartial("SomeChildViewName"); }

        @{<partial name="SomeChildViewName" for="CurrentDocumentTypeViewModel"/>}
</div>

我的父页面视图模型看起来像这样:

public class SampleModel
{
   public int ChildViewType { get; set; }
   public string ChildViewModelName { get; set; } 
}

为了完成这个,我有一些问题:

  1. 是否可以动态创建我的 ViewModel 对象 (DynamicObject) 以包含 子视图模型?

  2. 如何在我的父页面中动态包含子视图(和关联的视图模型)?

  3. 我应该使用还是@Html.Partial()/@{Html.RenderPartial}?

  4. 给定 Razor,是否可以做我正在尝试的事情?

请注意,在创建新应用时,使用标签库优先于 HTML 助手。

概念验证:

SampleModel 的更新版本:

public class SampleModel
{
    public object ChildViewModel { get; set; } 
    public string ChildViewName { get; set; }
}

还有一个简单的子模型

public class ModelForPartialOne
{
    public string SomeDemoProperty { get; set; }
}

在控制器中

private ModelForPartialOne GetModelForPartialOneWithDataFromDb()
{
    // just a mock db call
    return new ModelForPartialOne {SomeDemoProperty = "Hello from one"};
}

public IActionResult SomeControllerAction()
{
    const int childViewType = 42; // you will get this from somewhere
    
    switch (childViewType)
    {
        case 42:
            return View(new SampleModel
            {
                ChildViewModel = GetModelForPartialOneWithDataFromDb(),
                ChildViewName = "_partialOne",
            });
    }
}

在主 Razor 视图中

@model SampleModel

<div class="WhereToEmbedChildForm">
    <partial name="@Model.ChildViewName" model="@Model.ChildViewModel"/>
</div>

_partialOne.cshtml

@model ModelForPartialOne

<h1>Hello from partial one</h1>
<p>SomeDemoProperty: @Model.SomeDemoProperty</p>

为了避免臃肿的控制器,填充视图模型的逻辑应该委托给业务逻辑服务。

上述解决方案的替代方法是使用视图组件。

代码使用 Core 5 MVC 应用程序进行测试。

更新

OP 后来问我这个:

However, now I'm attempting to retrieve data from my partial view on a PostBack. The submit button lives on my parent page.

让我们像这样重写主视图:

@model SampleModel

<div class="WhereToEmbedChildForm">
    <form method="post" asp-action="@Model.PostbackAction">
        <partial name="@Model.ChildViewName" model="@Model.ChildViewModel"/>
        <button type="submit">Click Me</button>
    </form>
</div>

我们需要部分 _partialTwo.cshtml,其中的表单数据如下:

@model ModelForPartialOne

Some demo property:
<input asp-for="SomeDemoProperty">

将此 属性 添加到 SampleModelpublic string PostbackAction { get; set; }

并将控制器 GET 方法修改为 return this:

return View(new SampleModel
{
    ChildViewModel = GetModelForPartialOneWithDataFromDb(),
    ChildViewName = "_partialTwo",
    PostbackAction = "MyPostbackAction"
});

通过以上更改,我们可以打开带有表单的页面。现在我们需要一个控制器操作来处理回发。这就是乐趣所在,因为我们不能在 POST 方法中使用对象作为模型参数的类型;代码需要知道用于模型绑定的类型。

[HttpPost]
public IActionResult MyPostbackAction(ModelForPartialOne model)
{
    // do something
    return View("Index");
}