ASP.Net MVC 3 Razor: Section Defined But Not Rende

2019-02-04 03:30发布

问题:

I have the following layout template:

<div id="columns" class="@View.LayoutClass">
    <div id="mainColWrap">
        <div id="mainCol">
            @RenderBody()
        </div>
    </div>
    @if (View.ShowLeftCol){
    <div id="leftCol">
        @RenderSection("LeftCol", required: false)
    </div>
    }
    @if (View.ShowRightCol){
    <div id="rightCol">
        @RenderSection("RightCol", required: false)
    </div>
    }
</div>

If View.ShowLeftCol or View.ShowRightCol are set to false, I get the following error:


The following sections have been defined but have not been rendered for the layout page "~/Views/Shared/_Layout.cshtml": "RightCol".


I am trying to have a single layout template instead of trying to dynamically select a template at runtime. Is there a way to ignore this error and continue rendering? Can anyone think of another way to implement that would allow me to dynamically show/hide columns with Razor?

Thanks!

回答1:

Was given a suggestion on the ASP.net forums that works.

Essentially, if I define @section LeftCol in my view template but don't run any code that calls RenderSection in my layout, I get the error because it doesn't get called when View.ShowLeftCol is false. The suggestion was to add an else block and essentially throw away whatever contents are in the LeftCol section.

@if (View.ShowLeftCol)
{ 
<div id="leftCol"> 
    @RenderSection("LeftCol", false) 
</div> 
}
else
{
    WriteTo(new StringWriter(), RenderSection("LeftCol", false));
}

Based on the concern raised about memory I decided to test the following out as well. Indeed it also works.

@if (showLeft)
{
    <section id="leftcol">
        <div class="pad">
            @RenderSection("LeftColumn", false)
        </div>
    </section>
}
else
{
    WriteTo(TextWriter.Null, RenderSection("LeftColumn", false));
}

Also, at the top of my page, this is my new logic for showLeft/showRight:

bool showLeft = IsSectionDefined("LeftColumn");
bool showRight = IsSectionDefined("RightColumn");
bool? hideLeft  = (bool?)ViewBag.HideLeft;
bool? hideRight = (bool?)ViewBag.HideRight;
if (hideLeft.HasValue && hideLeft.Value == true) { showLeft = false; }
if (hideRight.HasValue && hideRight.Value == true) { showRight = false; }

Someone else said it didn't work for them, but it worked like a charm for me.



回答2:

@using System.Reflection;
@{
    HashSet<string> renderedSections = typeof(WebPageBase).GetField("_renderedSections", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField).GetValue(this) as HashSet<string>;
}

Then add to that hash set whatever section name you want to pretend to have rendered.



回答3:

@if (View.ShowLeftCol)
{ 
<div id="leftCol"> 
    @RenderSection("LeftCol", false) 
</div> 
}
else{  <!-- @RenderSection("LeftCol", false) -->  }

easier way!!