简体   繁体   English

调用局部视图

[英]Calling a Partial View

I've got a View rendering two dropdownlists.我有一个视图呈现两个下拉列表。 The controllers for the dropdownlists work fine.下拉列表的控制器工作正常。 They call methods in a repository class for the DB selections.他们为数据库选择调用存储库 class 中的方法。 Below the dropdownlists I'm trying to render a table of data in a partial view, in response to the dropdownlist selections.在下拉列表下方,我试图在部分视图中呈现数据表,以响应下拉列表选择。

The dropdowns in the View use a single model:视图中的下拉列表使用单个 model:

@model BudgetDemo.Models.BudgetsActualsViewModel

The Partial View displaying the table data uses IEnumerable:显示表格数据的分部视图使用 IEnumerable:

@model IEnumerable<BudgetDemo.Models.BudgetsActualsViewModel>

View (GetBudgetsActuals.cshtml):查看(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);
        }
    }
}

Partial View (_BudgetsActuals.cshtml):部分视图 (_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>
}

Controllers:控制器:

// 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);
}

What I'm trying to figure out is how to hook this all together.我想弄清楚的是如何将它们连接在一起。 It's blowing up here:这里炸了:

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

This is the error error message:这是错误的错误消息:

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'.

在此处输入图像描述 在此处输入图像描述

UPDATE更新

There seems to be a known issue with partial view if you're passing a model to the RenderPartial helper method and that model is null - it will default to the model of the containing view.如果您将 model 传递给 RenderPartial 辅助方法并且 model 是 null,那么部分视图似乎存在一个已知问题- 它将默认为包含视图的 model。 I have debugged this and from what I can see the model being passed to the helper method is not null, so I am at a loss.我已经对此进行了调试,据我所知,传递给辅助方法的 model 不是 null,所以我很茫然。

UPDATE 2更新 2

Apparently I was not alone regarding the issue of the model of the calling view being passed to the partial view.显然,我并不是唯一一个将调用视图的 model 传递给局部视图的问题。 This problem is addressed in .NET Core with the introduction of View Components:)这个问题在 .NET Core 中通过引入视图组件解决了:)

Well, what happens is, when you do Html.RenderPartial("_BudgetsActuals", Model);好吧,当你执行Html.RenderPartial("_BudgetsActuals", Model);时会发生什么? , it takes the model from the view in which the code is written, and tries to pass it as is to the partial view. ,它从编写代码的视图中获取 model,并尝试将其按原样传递给部分视图。 So here, based on the error screenshot in the question and the behavior of .net, BudgetDemo.Models.BudgetsActualsViewModel was passed to the partial view because GetBudgetsActuals.cshtml view takes that as a model. But, that is not right, because your partial view requires IEnumerable<BudgetDemo.Models.BudgetsActualsViewModel> as model. So, you need to actually store an instance of IEnumerable<BudgetDemo.Models.BudgetsActualsViewModel> in your BudgetDemo.Models.BudgetsActualsViewModel所以在这里,根据问题中的错误屏幕截图和 .net 的行为, BudgetDemo.Models.BudgetsActualsViewModel被传递到局部视图,因为GetBudgetsActuals.cshtml视图将其视为 model。但是,这是不对的,因为您的局部视图要求IEnumerable<BudgetDemo.Models.BudgetsActualsViewModel>为 model。因此,您需要在 BudgetDemo.Models.BudgetsActualsViewModel 中实际存储IEnumerable<BudgetDemo.Models.BudgetsActualsViewModel> BudgetDemo.Models.BudgetsActualsViewModel

Model Model

public class BudgetsActualsViewModel 
{
   // other properties

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

note: make sure to initialize it with the data on server or with a new instance when there is no data.注意:确保使用服务器上的数据或没有数据时使用新实例对其进行初始化。 Otherwise, it will throw null reference error.否则会抛出 null 引用错误。 You can initialize it in the constructor as well.您也可以在构造函数中对其进行初始化。

Controller (updated post method, this is just for example, you can simplify or update to your needs) 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);
}

Then do Html.RenderPartial("_BudgetsActuals", Model.BudgetActualCollection ) .然后执行Html.RenderPartial("_BudgetsActuals", Model.BudgetActualCollection ) Now proper model will be passed to the partial view.现在适当的 model 将被传递给局部视图。

Doing Html.RenderPartial("_BudgetsActuals", Model);Html.RenderPartial("_BudgetsActuals", Model); and (as op tried in comment below)和(正如操作在下面的评论中所尝试的那样)

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

are essentially the same with one difference.本质上是一样的,只有一处不同。 In first one, the model from main view will be passed whereas second will pass a new instance of the model.在第一个中,主视图中的 model 将被传递,而第二个将传递 model 的新实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM