Question

I have some simple <header> stuff in the file Shared/_Header.cshtml.

My Shared/_Layout.cshtml inserts that code by calling

@Html.Partial("_Header")

This worked fine so far.

Now I have some views that, in addition to the normal output via the @RenderBody(), should also add some icons in a specific place in the header.

I use@RenderSection()in a couple of my views, to create a sidebar, etc.

Now my idea was to create a section within my view (e.g Home/Details.cshtml) and add a RenderSection call to the _Header. The Layout would call the Header, and header in turn would see if the section existed and call it.

However that doesn't seem to work. I get the following error/exception:

The file "~/Views/Shared/_Header.cshtml" cannot be requested directly because it calls the "RenderSection" method.

Where lies my error? I know I can "nest" a partial call inside a section just fine. This code works just fine to tell the layout what file to use for a sidebar:

@section Sidebar{
    @Html.Partial("_SidebarDetails")
}

Does it not work the other way round?

I need way to define a block of HTML inside a view that is then put into a predefined place inside of a partial that is called by the layout.

Please help me understand how to do this.

Was it helpful?

Solution

If a view contains a RenderSection it is considered to be a layout page and cannot be rendered directly. See this question for more info: The file "~/Views/Position/Edit.cshtml" cannot be requested directly because it calls the "RenderSection" method

The easiest solution is to merge the partial view into the layout particularly if _Header.cshtml is only included on the layout page.

Another option is to override the header view with a custom header when needed.

In your layout page:

@if (IsSectionDefined("Header"))
{
    RenderSection("Header");
}
else
{ 
    @Html.Partial("_Header");
}

In your view (with custom icons):

@section Header
{
    @Html.Partial("_CustomHeader")
}

A further solution is to derive all your models from a base model class that contains custom icon data, e.g.

public abstract class BaseModel
{
    public List<Icon> Icons { get; set; }
}

public class ModelWithIcons : BaseModel
{
     public ModelWithIcons()
     {
        // Set up icon data
     }
}

The _header partial view is (still defined in the layout page) will use this base model and, with null checks, render any icons it finds:

@model BaseModel

<!-- Header HTML -->
@if (Model != null && Model.Icon)
{
    // Render icons
}
<!-- More HTML -->

The obvious downside here is that all your models must derive from the BaseModel class or the partial view will throw an error.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top