Use section in partial view

2020-04-02 09:45发布

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?

2条回答
我想做一个坏孩纸
2楼-- · 2020-04-02 10:08

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.

查看更多
ゆ 、 Hurt°
3楼-- · 2020-04-02 10:13

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

查看更多
登录 后发表回答