【问题标题】:Calling a Partial View调用局部视图
【发布时间】:2021-03-14 18:44:51
【问题描述】:

我有一个渲染两个下拉列表的视图。下拉列表的控制器工作正常。他们为数据库选择调用存储库类中的方法。在下拉列表下方,我尝试在部分视图中呈现数据表,以响应下拉列表选择。

视图中的下拉菜单使用单个模型:

@model BudgetDemo.Models.BudgetsActualsViewModel

显示表格数据的部分视图使用 IEnumerable:

@model IEnumerable<BudgetDemo.Models.BudgetsActualsViewModel>

查看(GetBudgetsActuals.cshtml):

@using (Html.BeginForm("GetBudgetsActuals", "BudgetsActuals", FormMethod.Post))
{
    ... DropDownLists and Submit button

    @if (Model.SelectedDepartment != null && Model.SelectedYear != null)
    {
        // Table headers
        @if (Model != null)
        {
            Html.RenderPartial("_BudgetsActuals", Model);
        }
    }
}

部分视图 (_BudgetsActuals.cshtml):

@model IEnumerable<BudgetDemo.Models.BudgetsActualsViewModel>
@foreach (var item in Model)
{
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Account)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.CostCenter)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.TotalCurrentMonthActual)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.TotalCurrentMonthBudget)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.TotalYTDActual)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.TotalYTDBudget)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.TotalVariance)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.TotalETCBudget)
        </td>
        <td>
             @Html.DisplayFor(modelItem => item.TotalEAC)
        </td>
    </tr>
}

控制器:

// GET: Render view with dropdowns
public ActionResult GetBudgetsActuals()
{
    try
    {
        // Populate Department dropdown and Year dropdown here
        repo = new BudgetDemoRepository();
        ModelState.Clear();

        return View(repo.GetBudgetsActuals());
    }
    catch
    {
        return View("Error");
    }
}

// POST: Grab data for department and year
[HttpPost]
public ActionResult GetBudgetsActuals(BudgetsActualsViewModel model)
{
    repo = new BudgetDemoRepository();
    if (ModelState.IsValid)
    {
        return View(repo.GetBudgetsActuals(model));
    }
    else
    {
        model.Departments = repo.GetBudgetsActuals().Departments;
        model.Years = repo.GetBudgetsActuals().Years;
        return View(model);    
    }
}

[ChildActionOnly]
public ActionResult 
    GetBudgetsActualsPartialData(BudgetsActualsViewModel model)
{
    repo = new BudgetDemoRepository();
    List<BudgetsActualsViewModel> dataVM = 
        repo.GetBudgetsActualsData(model);
    
    // RETURNING CORRECT DATA
    return PartialView("GetBudgetsActuals", dataVM);
}

我想弄清楚的是如何将这一切联系在一起。它在这里爆炸:

@if (Model != null)
{
    Html.RenderPartial("_BudgetsActuals", Model);
}

这是错误错误信息:

The model item passed into the dictionary is of type
'System.Collections.Generic.List`1[BudgetDemo.Models.BudgetsActualsViewModel]', 
but this dictionary requires a model item of type
'BudgetDemo.Models.BudgetsActualsViewModel'.

更新

如果您将模型传递给 RenderPartial 辅助方法并且该模型为空,则似乎有一个 known issuepartial view ——它将默认为包含视图的模型。我已经调试过了,从我可以看到传递给辅助方法的模型不为空,所以我很茫然。

更新 2

显然,我并不是唯一一个关于将调用视图的模型传递给局部视图的问题。这个问题在 .NET Core 中通过引入 View Components 得到解决:)

【问题讨论】:

  • 为什么不为您的表格返回一个List&lt;BudgetActualsViewModel&gt;,而不是为您的下拉列表创建一个具有属性的单个视图模型对象,然后为您的表格数据创建另一个List 类型的属性?
  • 那么当您更改下拉选择时会发生什么?它是否转到GetBudgetsActuals() 并返回一个视图如果您只需要更新页面上的表格,您需要执行一个ajax 调用操作方法并返回PartialView(viewName, model) 并使用javascript 填充html。
  • @Dave,我不想使用 AJAX 来解决这个问题。将更新问题。
  • 因此您有一个控制器,它从存储库中提取一些数据以响应下拉选择,将数据存储在IEnumerable 中,并将该数据传递到视图。然后视图将您的模型中继到局部视图以处理实际渲染。这听起来很标准。哪个部分不工作?将模型中继到部分是否存在问题?或者您是否正在尝试例如根据输入动态选择部分?我假设你正在使用例如@html.Partial()@html.RenderPartial() 调用实际的局部视图。您能否附上您的相关剃须刀代码?
  • @IrishChieftain 我在主视图中看不到RenderPartial。也许用错误、主视图代码、部分视图代码和控制器更新您的问题。删除所有其他代码,包括模型定义和 repo 代码。

标签: c# asp.net asp.net-mvc model-view-controller asp.net-mvc-5


【解决方案1】:

好吧,发生的情况是,当您执行 Html.RenderPartial("_BudgetsActuals", Model); 时,它会从编写代码的视图中获取模型,并尝试将其按原样传递给局部视图。所以在这里,根据问题中的错误截图和 .net 的行为,BudgetDemo.Models.BudgetsActualsViewModel 被传递到部分视图,因为GetBudgetsActuals.cshtml 视图将其作为模型。但是,这是不对的,因为您的部分视图需要 IEnumerable&lt;BudgetDemo.Models.BudgetsActualsViewModel&gt; 作为模型。因此,您需要在您的BudgetDemo.Models.BudgetsActualsViewModel 中实际存储IEnumerable&lt;BudgetDemo.Models.BudgetsActualsViewModel&gt; 的实例

型号

public class BudgetsActualsViewModel 
{
   // other properties

   public IEnumerable<BudgetDemo.Models.BudgetsActualsViewModel> BudgetActualCollection {get;set;}
}

注意:确保使用服务器上的数据或没有数据时使用新实例对其进行初始化。否则会抛出空引用错误。你也可以在构造函数中初始化它。

控制器(更新后的方法,这只是举例,您可以根据自己的需要进行简化或更新)

// GET: Render view with dropdowns
public ActionResult GetBudgetsActuals()
{
    try
    {
        // Populate Department dropdown and Year dropdown here
        repo = new BudgetDemoRepository();
        ModelState.Clear();

        return View(repo.GetBudgetsActuals());
    }
    catch
    {
        return View("Error");
    }
}

// POST: Grab data for department and year
[HttpPost]
public ActionResult GetBudgetsActuals(BudgetsActualsViewModel model)
{
    var repo = new BudgetDemoRepository();
    model.Departments = repo.GetBudgetsActuals().Departments;
    model.Years = repo.GetBudgetsActuals().Years;
    
    if (ModelState.IsValid)
    {
         model.BudgetActualCollection = repo.GetBudgetsActualsData(model);
    }
    else
    {
        model.BudgetActualCollection = new List<BudgetDemo.Models.BudgetsActualsViewModel>();
    }
    return View(model);
}

然后执行Html.RenderPartial("_BudgetsActuals", Model.BudgetActualCollection )。现在正确的模型将被传递给局部视图。

在做 Html.RenderPartial("_BudgetsActuals", Model); 和(在下面的评论中尝试过)

Html.RenderPartial("_BudgetsActuals", new BudgetDemo.Models.BudgetsActualsViewModel
{ 
   SelectedDepartment = Model.SelectedDepartment, 
   SelectedYear = Model.SelectedYear 
})

本质上是一样的,只有一个区别。在第一个中,将传递来自主视图的模型,而第二个将传递模型的新实例。

【讨论】:

  • 还没来得及检查。但我的理解是,局部视图并没有从视图中取模型。 MVC 中的一个错误意味着它只有在传递给 RenderPartial 助手的模型为空时才会这样做。查看链接?现在离开我的办公桌,但会试一试。谢谢。
  • 好的,快到了。您已经摆脱了将不正确的模型项传递给局部视图的原始问题。对于数据,尝试在parital视图中在Html.RenderPartial("_BudgetsActuals", Model.BudgetActualCollection )@foreach (var item in Model)上设置断点,看看是否有数据。
  • 没错,但这不是我们正在做的。我们在Html.RenderPartial("_BudgetsActuals", Model.BudgetActualCollection)中传递Model.BudgetActualCollection
  • @IrishChieftain 请打开一个新问题,因为它超出了原始问题的范围。包括完整的模型定义、主视图、验证以及它如何提交给控制器。
  • @IrishChieftain 谢谢,我不在桌面了。我明天去看看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-15
  • 2017-07-13
  • 2020-05-30
  • 2014-12-26
  • 1970-01-01
相关资源
最近更新 更多