Search code examples
c#asp.netrazorasp.net-coretag-helpers

Does RenderSection() work inside ASP.NET Core's <environment> tag-helper?


Layout has this:

<!DOCTYPE html>
<html>
<head>
  <environment names="Development">@RenderSection("devCss", required: false)</environment>
  <environment names="Staging,Production">@RenderSection("staproCss", required: false)</environment>
</head>
<body>
  @RenderBody()
  <environment names="Development">@RenderSection("devJs", required: false)</environment>
  <environment names="Staging,Production">@RenderSection("staproJs", required: false)</environment>
</body>
</html>

View has this:

@section devCss { <link rel="stylesheet" href="foo.css" asp-append-version="true" /> }
@section staproCss { <link rel="stylesheet" href="foo.min.css" asp-append-version="true" /> }
@section devJs {}
@section staproJs {}

<h1>hello</h1>

When RenderSection() is outside the <environment> tag, everything works.

When inside, as in above example, it fails with the unhelpful error of InvalidOperationException: The following sections have been defined but have not been rendered by the page at '_Layout.cshtml': 'staproCss, staproJs'. To ignore an unrendered section call IgnoreSection("sectionName").

That obviously makes no sense, as all sections were defined. And it complained about some, and not the others.

Does the <environment> tag-helper allow RenderSection() within it?


Solution

  • This answer is thanks to a comment by @user2818985.

    The environment which is not defined, will not emit the content within. Which means it won't emit the RenderSection() call. Which means the view will define a section foo { ... } which doesn't exist. Which fails, and thus the exception.

    To accomplish my original goal, I updated the layout:

    @inject Microsoft.AspNetCore.Hosting.IHostingEnvironment _env
    <!DOCTYPE html>
    <html>
    <head>
        <environment names="Development">
            @RenderSection("devCss", required: false)
        </environment>
        <environment names="Staging,Production">
            @RenderSection("staproCss", required: false)
        </environment>
        @if (_env.EnvironmentName == "Development" && IsSectionDefined("staproCss"))
        {
            IgnoreSection("staproCss"); 
        }
        @if (_env.EnvironmentName == "Staging,Production" && IsSectionDefined("devCss"))
        { 
            IgnoreSection("devCss"); 
        }
    </head>
    <body>
        @RenderBody()
        <environment names="Development">
            @RenderSection("devJs", required: false)
        </environment>
        <environment names="Staging,Production">
            @RenderSection("staproJs", required: false)
        </environment>
        @if (_env.EnvironmentName == "Development" && IsSectionDefined("staproJs")) 
        { 
            IgnoreSection("staproJs"); 
        }
        @if (_env.EnvironmentName == "Staging,Production" && IsSectionDefined("devJs")) 
        { 
            IgnoreSection("devJs"); 
        }
    </body>
    </html>
    

    So the sections are always defined, and so the child views never throw.