OzrenTkalcecKrznaric
OzrenTkalcecKrznaric

Reputation: 5646

Use section in partial view

In my shared layout I would like to have a "scripts" section to stuff it with all the scripts needed for page functionality.

Layout.cshtml

<html>
<head>
    <title>Test</title>
    <script src="@Url.Content("~/Scripts/jquery-2.0.3.js")" type="text/javascript"> </script>

    @RenderSection("Scripts", required: false)

</head>
<body>
    @RenderBody()
</body>
</html>

So, my view loads a specific javascript, and I want it to be in "scripts" section, and it's working.

Index.cshtml

@model PlatformaPu.Areas.Inventura.Models.Home.Index

@section Scripts {
    <script src="@Url.Content("~/Areas/Inventura/Scripts/Home/Index.js")" type="text/javascript"></script>
}

{CONTENT REMOVED FOR BREVITY}

@section Footer {
    @Html.Partial("~/Views/Shared/_AppSelector.cshtml", Model.AppSelector)
}

Finally, my view renders a partial and I have a javascript that this partial loads.

_AppSelector.cshtml

@model PlatformaPu.Models.Shared._AppSelector

@section Scripts {
    <script src="@Url.Content("~/Scripts/Shared/_AppSelector.js")" type="text/javascript"></script>
}

{CONTENT REMOVED FOR BREVITY}

...and this is NOT working - javascript tag is NOT rendered in "scripts" section

How can I do this?

Upvotes: 11

Views: 23934

Answers (2)

Electric Sheep
Electric Sheep

Reputation: 4320

As discussed in this question, it is not possible to use sections in a partial view:

Sections don't work in partial views and that's by design. You may use some custom helpers to achieve similar behavior, but honestly it's the view's responsibility to include the necessary scripts, not the partial's responsibility. I would recommend you using the @scripts section of the main view to do that and not have the partials worry about scripts.

You should add the script reference to the main view that references the partial.

Upvotes: 15

Paco Ferre
Paco Ferre

Reputation: 311

This is my first answer!

I've being working with webforms for years and now i'm dealing with MVC 5. Bit hard.

Perhaps is the wrong solution, but works :)

In Layout.cshtml. add second "ScriptsPartial" section

@RenderSection("ScriptsPartial", required: false)

In Index.cshtml, add ", new ViewDataDictionary(ViewData) { { "ViewPage", this } }"

@section Footer {
    @Html.Partial("~/Views/Shared/_AppSelector.cshtml", Model.AppSelector, new ViewDataDictionary(ViewData) { { "ViewPage", this } })
}

In _AppSelector.cshtml, remove this

@section Scripts {
    <script src="@Url.Content("~/Scripts/Shared/_AppSelector.js")" type="text/javascript"></script>
}

In _AppSelector.cshtml, add this in any place

@{
    if (ViewData.ContainsKey("ViewPage"))
    {
        System.Web.Mvc.WebViewPage viewPage = (System.Web.Mvc.WebViewPage)ViewData["ViewPage"];

        viewPage.DefineSection("ScriptsPartial", () =>
        {
            // viewPage.Write(Scripts.Render("~/AppSelector/Scripts")); // If you use a Bundle
            viewPage.WriteLiteral("<script src=\"" + Url.Content("~/Scripts/Shared/_AppSelector.js") + "\" type=\"text/javascript\"></script>");
        });
    }
}

Just "send" the View to the PartialView (no Parent property like in WebForms?) and use it to add content to "ScriptsPartial" section.

"ScriptsPartial" is needed because DefineSection throws an error "section already defined: Scripts"

So, no more than one PartialView can use "ScriptsPartial" section... not so good solution.

Best regards,

Paco Ferre

Upvotes: 3

Related Questions