使用两个不同的模型在父视图中加载局部视图

Loading a Partial View inside a Parent View with two different models

我的情况很简单,但我还没有完全掌握在父视图中使用可重用下拉列表部分视图的技术。

当我的视图尝试渲染时(在检索到正确的数据之后),我收到以下错误消息:

The model item passed into the dictionary is of type 'YeagerTechDB.Models.Category', but this dictionary requires a model item of type 'YeagerTechDB.ViewModels.Categories.CategoriesDDL'.

错误发生在行:

@Html.Partial("_SelectCategoryProjects");

我知道错误 的意思,但不知道如何解决它...我也一直认为,局部视图可以包含与它的父视图。

非常感谢您的回答,因为我显然错误地使用了这项技术。

我的 EnumDropDownListFor 的模型

using System;
using System.Runtime.Serialization;
using YeagerTechDB.Enums;

namespace YeagerTechDB.ViewModels.Categories
{
    [Serializable, DataContract(IsReference = true)]
    public class CategoriesDDL
    {
        [DataMember]
        public short CategoryID { get; set; }

        [DataMember]
        public CategoryTypeEnum CategoryType { get; set; }
    }
}

部分查看内容

@model YeagerTechDB.ViewModels.Categories.CategoriesDDL

@{
    ViewBag.Title = "CategoriesDDL";
}

<div class="form-group">
    <br />
    @Html.LabelFor(model => model.CategoryType, new { @class = "control-label required pull-left col-lg-3 col-md-3 col-sm-3 col-xs-3" })
    <div class="col-lg-8 col-md-8 col-sm-8 col-xs-8">
        @Html.EnumDropDownListFor(model => model.CategoryType, "Select Category", new { @class = "form-control" })
    </div>
</div>

相关控制器代码

// POST: Categories/CategoryProjects/Details
public ActionResult Details()
{
    return View();
}

[HttpPost]
// POST: Categories/CategoryProjects/Details/5
public async Task<ActionResult> Details(short id)
{
    if (id == 0)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Category category = await db.GetProjectsByCategoryIDAsync(id);

    if (category == null)
    {
        return HttpNotFound();
    }

    return View(category);
}

相关JS

function contentDetailsCatProjects()
{
    //var Url = $("#ddlCatProjects").val();

    $('#CategoryType').change(function (e)
    {
        getCatProjects();

        return false;
    });
}

function getCatProjects()
{
    var category_Input = {
        id: $('#CategoryType').val()
    };

    var Url = $("#categoryProjectsUrl").val();

    $.ajax({
        url: Url,
        data: JSON.stringify(category_Input),
        //data: AddAntiCSRFToken(JSON.stringify(category_Input)),
        dataType: "html",
        type: "POST",
        contentType: "application/json; charset=utf-8",
        async: true,
        success: function (data, status)
        {
            if (status == "success")
            {
                //data retrieved
            }
        },
        error: function (data, status, xhr)
        {
            if (xhr == "Not Found")
            {
                bootbox.dialog({
                    message: "No Projects exist for selected Category!",
                    title: "Category",
                    buttons: {
                        danger: {
                            label: "Warning!",
                            className: "btn-warning"
                        }
                    }
                });
            }
            else
            {
                bootbox.dialog({
                    message: "Projects cannot be retrieved for selected Category!" + '\n' + status + '\n' + xhr + '\n' + data,
                    title: "Category",
                    buttons: {
                        danger: {
                            label: "Danger!",
                            className: "btn-danger"
                        }
                    }
                });
            }
        }
    });
};

相关查看代码

@model YeagerTechDB.Models.Category

@{
    ViewBag.Title = "Categories";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<div>
    @Html.Partial("_SelectCategoryProjects");
</div>

@if (Model != null)
{ 
<div>
    <table class="table">
        <tr>
            <th>
                Associated Projects for selected Category
            </th>
            <th></th>
        </tr>
        <tr>
            <th>Project ID</th>
            <th>Project Description</th>
            <th>Project Name</th>
            <th>Quote</th>
            <th>Notes</th>
            <th>Created Date</th>
            <th>Updated Date</th>
        </tr>
        <tbody>
            @foreach (var item in Model.Projects)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(m => item.ProjectID)
                    </td>
                    <td>
                        @Html.DisplayFor(m => item.Description)
                    </td>
                    <td>
                        @Html.DisplayFor(m => item.Name)
                    </td>
                    <td>
                        @Html.DisplayFor(m => item.Quote)
                    </td>
                    <td>
                        @Html.DisplayFor(m => item.Notes)
                    </td>
                    <td>
                        @Html.DisplayFor(m => item.CreatedDate)
                    </td>
                    <td>
                        @Html.DisplayFor(m => item.UpdatedDate)
                    </td>
                </tr>
            }
        </tbody>
    </table>
</div>
}

<div>
    @Html.Hidden("categoryProjectsUrl", Url.Action("Details", "CategoryProjects", new { area = "Categories" }))
</div>

@section Scripts {
    <script>
        $(document).ready(function ()
        {
            if (typeof contentDetailsCatProjects == "function")
                contentDetailsCatProjects();
        });
    </script>
    }

部分视图可以引用父模型以外的模型。请参阅描述各种重载的 this article

在您的情况下,您将需要一种方法来实例化 CategoriesDDL 的实例,以便为 _SelectCategoryProjects 提供它期望的模型。可能有很多方法可以做到这一点,但我不建议将其作为 Details 的一部分。根据您的情况,您可以即时创建 CategoriesDDL 的实例,或者实现可以提供对象实例的静态方法。

要即时创建,请将 @Html.Partial("_SelectCategoryProjects") 替换为 @Html.Partial("_SelectCategoryProjects", new CategoriesDDL {...} )

或者,使用静态方法...

public static class MyCategoryControl
{
   public static CategoriesDDL GetCategoriesDDL() { ...some code to return instance of CategoriesDDL.. }
}

然后,将 @Html.Partial("_SelectCategoryProjects") 替换为 @Html.Partial("_SelectCategoryProjects", MyCategoryControl.GetCategoriesDDL())

您的主视图模型是 Category。默认情况下,当您使用 @Html.Partial("_SelectCategoryProjects"); 时,它会将 Category 模型传递给生成错误的方法。为 CategoriesDDLCategory 中包含一个 属性,例如

public class Category
{
  ....
  public CategoriesDDL Categories { get; set; }
}

并在主视图中

@Html.Partial("_SelectCategoryProjects", model.Categories)

请注意,您需要确保 Categories 已初始化(在控制器中或在无参数构造函数中),否则如果它为 null,则将传递 Category 模型而不是 CategoriesDDL

另一种选择是使用调用子操作,该操作使用 @Html.Action()

呈现部分视图