调用局部视图

Calling a Partial View

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

视图中的下拉列表使用单一模型:

@model BudgetDemo.Models.BudgetsActualsViewModel

显示 table 数据的分部视图使用 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 with - 它将默认为包含视图的模型。我已经对此进行了调试,据我所知,传递给辅助方法的模型不为空,所以我很茫然。

更新 2

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

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

中实际存储 IEnumerable<BudgetDemo.Models.BudgetsActualsViewModel> 的实例

型号

public class BudgetsActualsViewModel 
{
   // other properties

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

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

Controller(更新了post方法,这只是举例,您可以根据需要进行简化或更新)

// 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); 和(正如 op 在下面的评论中所尝试的那样)

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

基本相同,只有一处不同。在第一个中,将传递主视图中的模型,而第二个将传递模型的新实例。