【问题标题】:How do I conditionally/dynamically include Razor subpages in an Asp.Net Core Razor page?如何有条件地/动态地在 Asp.Net Core Razor 页面中包含 Razor 子页面?
【发布时间】:2021-09-25 15:23:32
【问题描述】:

这里是 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,是否有可能做我正在尝试的事情?

【问题讨论】:

  • 嗨,约翰。试图在之前的聊天中与您取得联系。我在那里写的是,您应该考虑注册活页夹,而不是注释很多类,就像我在发送给您的答案中显示的那样。您可能还想看看在您的控制器方法中使用 IFormCollection 作为替代方案。 BR

标签: .net asp.net-core razor


【解决方案1】:

请注意,在创建新应用时,使用标签库优于 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 后来问我这个问题:

但是,现在我正在尝试从我的部分视图中检索数据 回邮。提交按钮位于我的父页面上。

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

@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 View(new SampleModel
{
    ChildViewModel = GetModelForPartialOneWithDataFromDb(),
    ChildViewName = "_partialTwo",
    PostbackAction = "MyPostbackAction"
});

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

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

【讨论】:

  • 这符合我正在尝试做的事情。我有几个问题(这里是 Razor 的新手和动态替换)。 [1] - 是否可以动态设置 ?我有超过 20-30 个不同的可能子页面? [2] - 我如何加载子页面数据(从数据库中检索),每个子页面是否需要它自己的控制器,还是从主页面的控制器加载?
  • @JohnB:问题 #1:是的,我已经用这个更新了我的答案。问题 #2:请参阅我的更新答案。 BR
  • 就像宣传的魅力一样工作。这大大清理了我的实现。非常感谢!
  • @Roar.S - 你描述的一切都像宣传的那样工作。但是,现在我正在尝试从 PostBack 上的部分视图中检索数据。提交按钮位于我的父页面上。 LMK 如果我应该为此输入一个新问题。谢谢
  • @JohnB:我在答案的底部添加了回发解决方案。我希望我能理解您对此的要求。 BR
猜你喜欢
  • 2021-07-04
  • 1970-01-01
  • 1970-01-01
  • 2020-08-22
  • 2018-02-24
  • 1970-01-01
  • 2020-06-16
  • 2021-12-17
  • 2021-10-27
相关资源
最近更新 更多