Frage

Is it possible to have multiple @Model functions within one page?

I have a Views/Shared/_layout.cshtml page which has the following code to pull the navigation from an SQL Server 2012 database:

@model IEnumerable<WebApplication1.navigation_V>

<ul class="nav sf-menu clearfix">
    @foreach (var item in Model) {
        <li>@Html.MenuItem(item.title_TV, item.url_TV, "Home")</li>
    }
</ul>

This works fine on all views within the Views/Home folder, however the View/Accounts/Login.cshtml file has the following code:

@model WebApplication1.Models.LoginViewModel

Now I get the following error when trying to view the Account/Login page:

The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[WebApplication1.navigation_V]', but this dictionary requires a model item of type 'WebApplication1.Models.LoginViewModel'.

When writing the code I am not getting any red underline squiggles, the error only fires when trying to access the Account/Login page. This navigation function must be viewable on all pages, what I'm dreading next is actually getting the rest of the page content from the database in to these pages.

Any help would be much appreciated :-)

For further information I have included more code.

WebApplication1Entities.cs

using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;

namespace WebApplication1
{    
    public partial class WebApplication1Entities : DbContext
    {
        public WebApplication1Entities()
            : base("name=WebApplication1Entities")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }

        public virtual DbSet<navigation_V> navigation_V { get; set; }
    }
}   

navigation_V.cs

using System;
using System.Collections.Generic;

namespace WebApplication1
{
    public partial class navigation_V
    {
        public int navigation_ID { get; set; }
        public string title_TV { get; set; }
        public string url_TV { get; set; }
    }
}

Controllers/HomeController.cs:

public static class MenuExtensions
{
    public static MvcHtmlString MenuItem(
        this HtmlHelper htmlHelper,
        string text,
        string action,
        string controller
    )
    {
        var li = new TagBuilder("li");
        var routeData = htmlHelper.ViewContext.RouteData;
        var currentAction = routeData.GetRequiredString("action");
        var currentController = routeData.GetRequiredString("controller");
        if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) &&
            string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase))
        {
            li.AddCssClass("active");
        }
        li.InnerHtml = htmlHelper.ActionLink(text, action, controller).ToHtmlString();
        return MvcHtmlString.Create(li.ToString());
    }
}

namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
        private WebApplication1Entities db = new WebApplication1Entities();

        public ActionResult Index()
        {
            return View(db.navigation_V.ToList());
        }
    }
}

Views/Shared/Layout.cshtml

@model IEnumerable<WebApplication1.navigation_V>

<ul class="nav sf-menu clearfix">
    @foreach (var item in Model) {
        <li>@Html.MenuItem(item.title_TV, item.url_TV, "Home")</li>
    }
</ul>

I hope this make things a little clearer.

War es hilfreich?

Lösung

Instead of rendering navigation IEnumerable in layout you can write child action in your Home controller like this:

[ChildActionOnly]
public ActionResult Navigation()
{
    var navigationModel = ..
    // your code to retrieve IEnumerable<WebApplication1.navigation_V>
    // from DB

    return View(navigationModel);
}

View for this action is Views/Home/Navigation.cshtml:

@{ Layout = null; } // preventing recursive rendering
@model IEnumerable<WebApplication1.navigation_V>

<ul class="nav sf-menu clearfix">
    @foreach (var item in Model) {
        <li>@Html.MenuItem(item.title_TV, item.url_TV, "Home")</li>
    }
</ul>

And code for _layout.cshtml, replace your old navigation code with this one:

@{ Html.RenderAction("Navigation", "Home"); }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top