C# 调用局部视图

C# 调用局部视图,c#,asp.net,asp.net-mvc,model-view-controller,asp.net-mvc-5,C#,Asp.net,Asp.net Mvc,Model View Controller,Asp.net Mvc 5,我有一个视图渲染了两个下拉列表。DropDownList的控制器工作正常。它们在存储库类中为DB选择调用方法。在dropdownlists下面,我尝试在部分视图中呈现一个数据表,以响应dropdownlist的选择 视图中的下拉列表使用单个模型: @model BudgetDemo.Models.BudgetsActualsViewModel 显示表格数据的局部视图使用IEnumerable: @model IEnumerable<BudgetDemo.Models.BudgetsAct

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

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

@model BudgetDemo.Models.BudgetsActualsViewModel
显示表格数据的局部视图使用IEnumerable:

@model IEnumerable<BudgetDemo.Models.BudgetsActualsViewModel>
部分视图(\u BudgetsActuals.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);
        }
    }
}
@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);
}
这是错误消息:

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 helper方法,并且该模型为null,则会出现一个with,它将默认为包含视图的模型。我已经对此进行了调试,从中可以看出,传递给helper方法的模型不是空的,所以我不知所措

更新2


显然,在调用视图的模型被传递给部分视图的问题上,我并不是唯一一个这样做的人。这个问题在.NETCore中通过引入视图组件得到了解决:)

那么,当您执行
Html.RenderPartial(“\u BudgetsActuals”,Model”)时,会发生什么呢,它从编写代码的视图中获取模型,并尝试按原样将其传递到局部视图。因此,在这里,根据问题中的错误截图和.net的行为,
BudgetDemo.Models.BudgetActualsViewModel
被传递到部分视图,因为
GetBudgetActuals.cshtml
视图将其作为一个模型。但是,这是不对的,因为局部视图需要
IEnumerable
作为模型。因此,您需要在
BudgetDemo.Models.BudgetsActualsViewModel

型号

public class BudgetsActualsViewModel 
{
   // other properties

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

本质上是相同的,但有一点不同。在第一个视图中,将传递主视图中的模型,而第二个视图将传递模型的新实例。

而不是为表返回
列表,为什么不为下拉列表创建一个具有属性的单一视图模型对象,然后为表格数据创建另一个
List
类型的属性?那么,当您更改下拉选择时会发生什么?它是否转到
getBudgetActuals()
并返回一个视图如果您只需要更新页面上的表,您需要对action方法执行ajax调用并返回
PartialView(viewName,model)
并使用javascript填充html。@Dave,我不想使用ajax来解决这个问题。将更新问题。因此,您有一个控制器,可以根据下拉选择从存储库中提取一些数据,将数据存储在
IEnumerable
中,并将该数据发送到视图。然后,视图将模型中继到局部视图以处理实际渲染。这听起来很标准。哪一部分坏了?将模型传递给部分用户是否存在问题?或者您正在尝试(例如)根据输入动态选择部分?我假设您正在使用例如
@html.Partial()
@html.RenderPartial()
来调用实际的部分视图。你能包括你的相关剃须刀代码吗?@IrishChieftain我在主视图中看不到
RenderPartial
。可能会用错误、主视图代码、部分视图代码和控制器更新您的问题。删除所有其他代码,包括模型定义和回购代码。还没有机会检查它。但我的理解是,局部视图并不从视图中获取模型。MVC中的一个bug意味着,只有当传递给RenderPartial助手的模型为空时,MVC才会这样做。查看链接?现在离开我的办公桌,但我会尝试一下。谢谢。好的,就快到了。您已经摆脱了将不正确的模型项传递到局部视图的原始问题。对于数据,请尝试在parital视图中的
Html.RenderPartial(“\u BudgetActuals”,Model.BudgetTacualCollection)
@foreach(模型中的var项)
上设置断点,查看是否有数据。这是正确的,但这不是我们正在做的。我们在
Html.RenderPartial(“\u BudgetsActuals”,Model.BudgetActualCollection)”中通过
Model.BudgetActualCollection
@IrishChieftain请打开一个新问题,因为它超出了原始问题的范围。包括完整的模型定义、主视图、验证以及如何提交给控制器。@IrishChieftain谢谢,我不在桌面上了。我明天去看看。
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", new BudgetDemo.Models.BudgetsActualsViewModel
{ 
   SelectedDepartment = Model.SelectedDepartment, 
   SelectedYear = Model.SelectedYear 
})