2

I am trying to create the menus in my _Layout page using a partial view called _Menus which reads from a Json file on my server. But I can't figure out how to call a partial view with a model from the layout page.

Here is the _Menu.cshtml page, which is in the Shared folder:

@model IEnumerable<LangSite_151209.Models.MenuItem>

<div id="menu" class="largescreen_show smallscreen_hide" data-display="flex">
    <div id="menu_left" class="menu_item">

        @foreach (var mainMenuItem in Model)
        {
           // A bunch of stuff with the model that draws the menu
        }
   </div>
</div>

Here is how I call it in the _Layout page:

<!DOCTYPE html>

<html lang="en">
<head>
     <!-- Meta and script stuff -->
</head>
<body style="overflow:hidden;"> 


    <div id="fg">

        <div id="mobile_wrapper">
        @Html.Partial("../Shared/_Menu")
        </div>

    </div>
    <!-- A bunch of footer stuff that's irrelevant here -->
</html>

I have tried returning the partial view with a SharedController that opens the Json file and turns it into a model for the partial, as follows:

public class SharedController : Controller
{
    // GET: Shared
    [ChildActionOnly]
    public ActionResult _Menu()
    {
        string filePath = HostingEnvironment.MapPath(@"~/App_Data/MenuItems.json");
        StreamReader sr = new StreamReader(filePath);

        string JsonString = sr.ReadToEnd();
        JsonSerializerSettings settings = new JsonSerializerSettings
        {
            TypeNameHandling = TypeNameHandling.All
        };
        var menuItems = JsonConvert.DeserializeObject<List<MenuItem>>(JsonString, settings);

        return View(menuItems.ToList());
    }       
}

But when I try this I get a NullReferenceException on the Model: "Object reference not set to an instance of an object." Apparently you can't pass a model to a partial that way. I know that the code that reads the Json object works because when I use it the same code on a regular (non-partial) page it passes the model correctly and the script draws the menu.

Normally if I want to pass a model to a partial I just put the model in the main page and pass it that way. But I don't know how to put a model in the _Layout. Is that how I should to it? Or is there a better way?

1
  • You can pass the model to a partial like this: @Html.Partial("viewName", Model). The problem is that the model has to be already populated. Commented Apr 12, 2016 at 18:58

1 Answer 1

3

The line @Html.Partial("../Shared/_Menu") will not execute your _Menu action method. Your _Menu.cshtml partial view is strongly typed to a list of MenuItem's. So either you should explicitly pass it when calling the Html.Partial method or your the main view ( which is calling this partial) should be also typed to the same collection.

You should use Html.Action method instead of Html.Partial.

@Html.Action("_Menu", "Shared")

This will execute the _Menu action method and pass the needed data (list of MenuItem) to the corresponding partial view.

Sign up to request clarification or add additional context in comments.

2 Comments

This makes the controller code work, thanks. Now I'm getting the error: "An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll" on the line: string filePath = HostingEnvironment.MapPath(@"~/App_Data/MenuItems.json");
But that might be a different question.

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.