开发者

RenderSection() inside partial with master page

I have a partial "Sidebar" added to the master page (Layout) and inside this partial I'm using:

@RenderSection("SearchList", required: false)

On one of the views that uses the master page I'm doing:

@section SearchList {
    // bunch of html
}

but it's giving me the error:

The file "~/Views/Shared/_SideBar.cshtml" cannot be requested directly because it calls the "IsSectionDefined" m开发者_如何学JAVAethod.

What's wrong here?


What you are trying to do is not currently supported in Razor. Sections only work between the view page and its immediate layout page.


When creating your layout view you might want to put some pieces seperatly into partial views.

You might also encounter the need to render sections that need to be placed into the markup of one of these partial views. However, since partial views do not support RenderSection logic you'll have to work around this.

You can render sections in a partial views by passing the RenderSection result from your Layout page as the model of the partial view. You can do this by putting this line of code in your _Layout.cshtml.

_Layout.cshtml

@{ Html.RenderPartial("_YourPartial", RenderSection("ContextMenu", false));}

Then in _YourPartial.cshtml you can render the section passed along as the model in the Html.RenderPartial call on the _Layout view. You check if the model is null just in case your section is not required.

_YourPartial.cshtml

@model HelperResult
@if (Model != null)
{
    @Model
}


It is possible to solve this with razor helpers. It's kinda elegantly-hacky™ but it did the job for me.

So in a parent view you define a helper:

@helper HtmlYouWantRenderedInAPartialView()
{
    <blink>Attention!</blink>
}

Then when you render partial, you pass this helper to it

@Html.Partial("somePartial", new ViewDataDictionary { { "OptionalSection1", (Func<HelperResult>)(HtmlYouWantRenderedInAPartialView) } })

Then inside a partial view you call this helper like so

<div>@ViewData.RenderHelper("OptionalSection1")</div>

Finally you need to have this extension method to simplify the "calling" part

public static HelperResult RenderHelper(this ViewDataDictionary<dynamic> viewDataDictionary, string helperName)
{
    Func<HelperResult> helper = viewDataDictionary[helperName] as Func<HelperResult>;
    if (helper != null)
    {
        return helper();
    }

    return null;
}

So the whole point is to pass a delegate of this helper and then when the child view calls it, the contents get rendered where you want them.

The end result of a child view would look like this

<div><blink>Attention!</blink></div>


While Bosken85's answer is close, it doesn't quite work when the section is not defined in your view. The if statement isn't used, (an exception is thrown first.) You need to overload the RenderPartial including 3 parameters so that the non-existent RenderSection isn't ignored, causing the wrong model to be passed to the partial layout.

In _Layout.cshtml (your overall layout) you use:

@{Html.RenderPartial("_Partial", RenderSection("sectionNameGoesHere", false), new ViewDataDictionary());}

In _Partial.cshtml (your partial layout that wants to define a RenderSection) you use:

@model HelperResult
@Model

In Index.cshtml (a layout that uses _Layout.cshtml for it's layout and you want to put some content into the partial layout's section) you use:

@section sectionNameGoesHere{stuff you want in the section goes here}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜