使用两个不同的模型在父视图中加载局部视图
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
模型传递给生成错误的方法。为 CategoriesDDL
在 Category
中包含一个 属性,例如
public class Category
{
....
public CategoriesDDL Categories { get; set; }
}
并在主视图中
@Html.Partial("_SelectCategoryProjects", model.Categories)
请注意,您需要确保 Categories
已初始化(在控制器中或在无参数构造函数中),否则如果它为 null,则将传递 Category
模型而不是 CategoriesDDL
另一种选择是使用调用子操作,该操作使用 @Html.Action()
呈现部分视图
我的情况很简单,但我还没有完全掌握在父视图中使用可重用下拉列表部分视图的技术。
当我的视图尝试渲染时(在检索到正确的数据之后),我收到以下错误消息:
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
模型传递给生成错误的方法。为 CategoriesDDL
在 Category
中包含一个 属性,例如
public class Category
{
....
public CategoriesDDL Categories { get; set; }
}
并在主视图中
@Html.Partial("_SelectCategoryProjects", model.Categories)
请注意,您需要确保 Categories
已初始化(在控制器中或在无参数构造函数中),否则如果它为 null,则将传递 Category
模型而不是 CategoriesDDL
另一种选择是使用调用子操作,该操作使用 @Html.Action()