2016-03-11 34 views
2

請對我溫柔。我在這個網站上爲其他人閱讀了很多MVC的答案,但現在我找到了一些找不到答案的地方。將多個模型傳遞給_Layout.cshtml,其中一個創建動態菜單

通過課程我創建了一個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; } 
    } 
} 

下面是來自控制器的代碼段:

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表動態構建的菜單,然後將視圖模型傳遞給_Layout.cshtml,以便菜單將顯示在所有頁面上。爲了不使雜亂的代碼與工作LoginDetails代碼,我創建了一個名爲SiteMenu的新文件夾,並在其中測試菜單的索引頁。 它太偉大的工作,但後來我決定只重新運行LoginDetails部分,以確保仍然工作,並得到了以下錯誤:

Exception Details: System.InvalidOperationException: The model item passed into the dictionary is of type System.Collections.Generic.List 1[MVC_EFCRUD.Models.LoginDetail], but this dictionary requires a model item of type 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; } 
    } 
} 

段:從_Layout.cshtml

namespace MVC_EFCRUD.Controllers 
{ 
    public class SiteMenuController : Controller 
    { 
     // GET: SiteMenu 
     public ActionResult Index() 
     { 

      tapnamron_PNMSiteMenu ent = new tapnamron_PNMSiteMenu(); 

      return View(ent.GetSiteMenu().ToList()); 
     } 
    } 
} 

段:

@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) 
    { 

我嘗試了幾種方法來f九,但沒有運氣。 這裏是一堆remmed出碼我在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>; 
}*@ 

我意識到我真的不想因爲將是更多的東西不涉及LoginDetails但當然會利用每一個頁面上的菜單站點中的多個模型添加到佈局頁。我想也許是部分觀點或嵌套觀點,但從我發現的內容來看,仍然會存在衝突。

所以,我想要的是一種使用多個模型的方法,並且在每個頁面上還包含動態創建的菜單(也是使用模型構建的)?

非常感謝!

+0

僅供參考,要在一個視圖中使用多個模型,您必須創建一個新的ViewModel,然後將其屬性類型設置爲multip le模型。 SO每個模型的每個屬性。這樣,您將擁有一個Viewmodel,可以在內部保存多個模型。 Stephen提供的答案適合您的情況。 –

回答

1

你採取了錯誤的做法。而不是將模型傳遞給佈局,請在佈局頁面中使用Html.RenderAction()生成菜單。用[ChildActionOnly]屬性標記SiteMenuController控制器的Index()方法(以便它不能直接從瀏覽器中調用),並將其更改爲返回菜單的部分視圖。

然後在_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> 
} 
+0

謝謝,斯蒂芬!我假設我應該將此SiteMenu視圖轉換爲嵌套的局部佈局頁面,是否正確? –

+0

不是。只是局部視圖。從'_Layout.cshtml'中刪除'@model IEnumerable '語句,並用'@model IEnumerable '創建一個局部視圖 - '/ Views/SiteMenu/Index.cshtml'。然後將與菜單html相關的所有內容複製到該部分視圖中,並在佈局中用'@ {Html.RenderAction(「Index」,「SiteMenu」)替換它。 }' –

+0

我已經編輯了答案,以提供更多的細節 –

相關問題