请对我温柔。我已经在这个网站上为其他人阅读了大量的MVC答案,但现在我找到了一些我无法找到答案的答案。
通过课程我创建了一个LoginDetails项目,其中一个viewmodel从控制器传递到每个视图,一切都很顺利。
模型(来自SQL表):
namespace MVC_EFCRUD.Models
{
using System;
using System.Collections.Generic;
public partial class LoginDetail
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
}
以下是Controller的摘录:
using MVC_EFCRUD.Models;
namespace MVC_EFCRUD.Controllers
{
public class LoginDetailsController : Controller
{
private tapnamron_PNMEntities db = new tapnamron_PNMEntities();
// GET: LoginDetails
public ActionResult Index()
{
return View(db.LoginDetails.ToList());
}
以下是LoginDetails文件夹的索引视图中的代码段:
@model IEnumerable<MVC_EFCRUD.Models.LoginDetail>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.UserName)
</th>
之后我决定创建一个从SQL表动态构建的菜单,然后将viewmodel传递给_Layout.cshtml,这样菜单就会出现在所有页面上。为了不使用工作的LoginDetails代码使这个代码混乱,我创建了一个名为SiteMenu的新文件夹,其中包含一个索引页面,我将测试该菜单。 它也很好,但后来我决定重新运行LoginDetails部分,以确保它仍然有用并得到以下错误:
异常详细信息:System.InvalidOperationException:模型项 传入字典的类型 System.Collections.Generic.List 1 [MVC_EFCRUD.Models.LoginDetail], 但是这个字典需要一个类型的模型项 System.Collections.Generic.IEnumerable 1 [MVC_EFCRUD.Models.uspGetSiteMenu_Results]。
所以,从我在这个网站上看到的内容(非常感谢)我想,因为我将一个viewmodel传递给我的菜单的_Layout页面,这与LoginDetails页面上的模型冲突,因为它们都是访问相同的_Layout页面。 以下是SiteMenu模型(使用存储过程检索):
namespace MVC_EFCRUD.Models
{
using System;
public partial class uspGetSiteMenu_Results
{
public int MenuID { get; set; }
public int ParentID { get; set; }
public string SiteName { get; set; }
public string Url { get; set; }
public string Target { get; set; }
}
}
来自Controller的代码段:
namespace MVC_EFCRUD.Controllers
{
public class SiteMenuController : Controller
{
// GET: SiteMenu
public ActionResult Index()
{
tapnamron_PNMSiteMenu ent = new tapnamron_PNMSiteMenu();
return View(ent.GetSiteMenu().ToList());
}
}
}
来自_Layout.cshtml的代码段
@model IEnumerable<MVC_EFCRUD.Models.uspGetSiteMenu_Results>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
<link href="~/Content/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="~/Scripts/modernizr-2.6.2.js"></script>
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
@using System.Web.Optimization;
@Styles.Render("~/Content/css")
</head>
<body>
<nav class="navbar navbar-inverse navbar-static-top marginBottom-0" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
</div>
<div class="collapse navbar-collapse" id="navbar-collapse-1">
<ul class="nav navbar-nav">
@foreach (var item in Model.Where(m => m.ParentID == 0))
{
switch (item.SiteName)
{
我尝试了几种方法来解决这个问题,但没有运气。 以下是我在HomeController中提供的一堆已解决的代码:
namespace MVC_EFCRUD.Controllers
{
public class HomeController : Controller
{
//tapnamron_PNMEntities m1 = new tapnamron_PNMEntities();
//tapnamron_PNMSiteMenu m2 = new tapnamron_PNMSiteMenu();
//LoginDetail modelLoginDetail = new LoginDetail();
//uspGetSiteMenu_Results ModeluspGetSiteMenu_Results = new uspGetSiteMenu_Results();
// GET: Home
public ActionResult Index()
{
//List<object> model = new List<object>();
//model.Add(modelLoginDetail);
//model.Add(ModeluspGetSiteMenu_Results);
//var model = Tuple.Create<IEnumerable<string>, IEnumerable<string>>(LoginDetail, uspGetSiteMenu_Results);
//return View(model);
//var viewmodel = new MyModels
//{
// uspGetSiteMenu_Results = uspGetSiteMenu_Results,
// LoginDetail = LoginDetail
//};
//var myModels = new MyModels();
return View();
}
}
}
我在_Layout中也有这个,但是如果它给你造成混淆(它是从HomeController传递的话)就把它删掉了:
@*@model IEnumerable<object>
@{
List<MVC_EFCRUD.Models.LoginDetail> lstLoginDetails = Model.ToList()[0]
as List<MVC_EFCRUD.Models.LoginDetail>;
List<MVC_EFCRUD.Models.uspGetSiteMenu_Results> lstSiteMenu = Model.ToList()[1]
as List<MVC_EFCRUD.Models.uspGetSiteMenu_Results>;
}*@
我意识到我真的不想在Layout页面中添加多个模型,因为与LoginDetails无关的网站会有更多东西,但当然会在每个页面上使用菜单。我想可能是一些部分视图或嵌套视图,但从我发现的仍然会有冲突。
那么,我想要的是一种使用多个模型的方法,并且仍然在每个页面上包含动态创建的菜单(也使用模型构建)?
非常感谢!
答案 0 :(得分:1)
你采取了错误的做法。在布局页面中,使用Html.RenderAction()
生成菜单,而不是将模型传递给布局。使用Index()
属性标记SiteMenuController
控制器的[ChildActionOnly]
方法(以便无法直接从浏览器调用)并更改它以返回菜单的部分视图。
然后在_Layout.cshtml
文件中,使用
@{ Html.RenderAction("Index", "SiteMenu"); }
在布局页面中输出菜单。
_Layout.cshtml(否@model
)
<head>
....
</head>
<body>
@{ Html.RenderAction("Index", "SiteMenu"); }
@RenderBody()
</body>
/Views/SiteMenu/Index.cshtml(包含与菜单相关的所有html的局部视图)
@model IEnumerable<MVC_EFCRUD.Models.uspGetSiteMenu_Results>
<nav class="navbar navbar-inverse navbar-static-top marginBottom-0" role="navigation">
....
@foreach (var item in Model.Where(m => m.ParentID == 0))
{
....
}
</nav>
控制器
[ChildActionOnly]
public ActionResult Index()
{
tapnamron_PNMSiteMenu ent = new tapnamron_PNMSiteMenu();
return PartialView(ent.GetSiteMenu().ToList()); // .ToList() not necessary as the view is IEnemerable<T>
}