0

I am very new to this and am doing a little project to get to know how it all works.

So I'm looking to create a header image area on each page by placing the code in the "_Layout.cshtml" file and attempting to control what image displays according to "ViewBag.Title".

I have broken the code up into the pages, followed by a pic. of the error. I just can't work out what the problem is.

HomeController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace WebSite_Project_1.Controllers
{
public partial class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult About()
    {
        ViewBag.Message = "Your application description page.";

        return View();
    }

    public ActionResult Contact()
    {
        ViewBag.Message = "Your contact page.";

        return View();
    }

    [ActionName("Funny-Bones")]
    public ActionResult FunnyBones()
    {
        ViewBag.Message = "This is funny bones.";

        return View();
    }
    public class Headers
    {
        public string HeaderName { get; set; }
        public string PageName { get; set; }
        public int HeaderWidth { get; set; }
        public int HeaderHeight { get; set; }
        public string HeaderType { get; set; }
    }
    public ActionResult HeaderImages()
    {
            var model = new List<Headers>();

            model.Add(new Headers { HeaderName = "home", PageName = "Home Page", HeaderWidth = 2200, HeaderHeight = 1172, HeaderType = ".png" });
            model.Add(new Headers { HeaderName = "about", PageName = "About", HeaderWidth = 2200, HeaderHeight = 1172, HeaderType = ".png" });
            model.Add(new Headers { HeaderName = "contact", PageName = "Contact", HeaderWidth = 2200, HeaderHeight = 1172, HeaderType = ".png" });
            model.Add(new Headers { HeaderName = "funnybones", PageName = "Funny Bones", HeaderWidth = 2200, HeaderHeight = 1172, HeaderType = ".png" });

            return View(model);
    }
}
}

_Layout.cshtml

@model IEnumerable<WebSite_Project_1.Controllers.HomeController.Headers>

<div class="headersImage">
        @foreach (var item in Model)
        {
            if (@item.PageName == @ViewBag.Title)
            {
                <img src="~/Content/Images/@[email protected]" title="@item.HeaderName" />
            }
        }
</div>
@RenderBody()

The problem starts when I try and publish it and then i get this error pointing to Model in the "foreach" loop.

I'm not a 100% sure the loop is right, but haven't been able to get that far yet.

Link to MVC error

6
  • this usage is not suggested way, you should define your model class in model folder and then create List instance of it by importing WebSite_Project_1.Models namespace Commented Aug 4, 2017 at 14:56
  • You should post the error as text instead of an image so others with the same error can find it using search engines. Commented Aug 4, 2017 at 14:56
  • then change this line IEnumerable<WebSite_Project_1.Controllers.HomeController.Headers> with IEnumerable<WebSite_Project_1.Models.Headers> and write your foreach code in HeaderImages view instead of layout to dont get NullExeption Commented Aug 4, 2017 at 14:57
  • Hi hsnbl,I changed that line to your suggestion and a red squiggly line appeared under Models. And that's with me creating a new file in 'Shared' called HeaderImages.cshtml and putting a line in _Layout.cshtml in its place to pull it in which is @RenderPage("HeaderImages.cshtml") Commented Aug 4, 2017 at 15:03
  • When I roll over Models with the red squiggly line I get the following message, and again I'm really new to this so I'm not fully getting it. The type or namespace name 'Models' does not exist in namespace 'Website_Project_1' (are you missing an assembly reference) Commented Aug 4, 2017 at 15:13

1 Answer 1

1

You should never specify a model for a layout. The model passed in will always be the one for the view, which almost invariably, will not be the same one the layout is wanting.

For things like this, you should use child actions. Essentially, just take your existing HeaderImages action, add the [ChildActionOnly] attribute (which prevents it from being routed to directly), and change the return to:

return PartialView("_HeaderImages", model);

You can call the view whatever you want, but essentially it would just have the following:

@model IEnumerable<WebSite_Project_1.Controllers.HomeController.Headers>

<div class="headersImage">
    @foreach (var item in Model)
    {
        if (@item.PageName == @ViewBag.Title)
        {
            <img src="~/Content/Images/@[email protected]" title="@item.HeaderName" />
        }
    }
</div>

Finally, in your layout, remove the model definition line and replace the header image code currently there with:

@Html.Action("HeaderImages", "Home")

EDIT

Sorry, I missed one thing. The child action will render in a separate context from the main view/layout (that's sort of the point). However, that means it has its own ViewBag, so you can't access the ViewBag from the main action directly. Instead, you'll need to pass it in as a route value:

@Html.Action("HeaderImages", "Home", new { title = ViewBag.Title })

Then, modify your child action to accept this param, and set its ViewBag:

[ChildActionOnly]
public ActionResult HeaderImages(string title)
{
    ...
    ViewBag.Title = title;
    return PartialView("_HeaderImages", model);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.