Search code examples
c#asp.net-corerazorrazor-pages

Razor Pages _Layout.cshtml, and strongly typed partial pages


There are a lot of similar questions, but no good answers. This is my attempt:

I want to use a partial view in _Layout.cshtml for a menu that will appear on every page.

My _Layout.cshtml:

 <div id="navbar" class="navbar-collapse">
    <partial name="_TopLevelMenu" model="Model.MainMenuModel" />
 </div>

My _TopLevelMenu.cshtml partial:

@model List<Data.Models.MainMenuModel>

<ul id="ulMainMenu" class="nav navbar-nav">
    
@foreach (var item in Model){
    <li @item.NavId>
      <a href="@item.NavigationUrl">@item.DisplayName</a>
    </li>
}
</ul>

My error:

RuntimeBinderException: 'MyApp.Pages.IndexModel' does not contain a definition for 'MainMenuModel'

Things I've tried:

"Pass the model" - I get the same error when I do this, and besides, Visual Studio strongly advises me to use the Partial tag helper instead.

Use the partial tag without a named model, which gives me this error: InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'MyApp.Pages.IndexModel', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.List1[MyApp.Data.Models.MainMenuModel]'.`

I tried it with just MainMenuModel but Visual Studio tells me it's a type and I can't use a type for my model.

I looked at this website for guidance, and it unhelpfully uses some of my key search words ("menu", "layout") but doesn't use the _Layout.cshtml page as part of the example.

If I do <partial name="_TopLevelMenu" model=new MainMenuModel()" /> I don't get errors but I also don't get my data from the partial to populate.

What must I do to properly have a partial be the menu items on all pages?


Solution

  • Chen has provided a good explanation of the cause of your error message and a resolution, and also notes that when passing models to partials in a layout, you must define the model in every page that references the layout. You could do this by implementing a base class for your pages and define the model there, and then derive all your pages from the base class, but in practice, that can become very cumbersome to manage.

    I recommend using View Components for segments of UI that go into layouts, where the UI segment depends on server-side logic for generating the content:

    They are a little more complicated to set up than a partial, but they are responsible for generating their own data.