我在我的_Layout.cshtml中定义了这个部分

@RenderSection("Scripts", false)

我可以很容易地从视图中使用它:

@section Scripts { 
    @*Stuff comes here*@
}

我正在努力解决的问题是如何从局部视图将一些内容注入到这个部分中。

让我们假设这是我的视图页面:

@section Scripts { 

    <script>
        //code comes here
    </script>
}

<div>
    poo bar poo
</div>

<div>
  @Html.Partial("_myPartial")
</div>

我需要在脚本部分中从_myPartial partial视图中注入一些内容。

我该怎么做呢?


当前回答

普路托的想法比较好:

CustomWebViewPage.cs:

    public abstract class CustomWebViewPage<TModel> : WebViewPage<TModel> {

    public IHtmlString PartialWithScripts(string partialViewName, object model) {
        return Html.Partial(partialViewName: partialViewName, model: model, viewData: new ViewDataDictionary { ["view"] = this, ["html"] = Html });
    }

    public void RenderScriptsInBasePage(HelperResult scripts) {
        var parentView = ViewBag.view as WebPageBase;
        var parentHtml = ViewBag.html as HtmlHelper;
        parentView.DefineSection("scripts", () => {
            parentHtml.ViewContext.Writer.Write(scripts.ToHtmlString());
        });
    }
}

观点\ web . config:

<pages pageBaseType="Web.Helpers.CustomWebViewPage">

观点:

@PartialWithScripts("_BackendSearchForm")

部分(_BackendSearchForm.cshtml):

@{ RenderScriptsInBasePage(scripts()); }

@helper scripts() {
<script>
    //code will be rendered in a "scripts" section of the Layout page
</script>
}

布局页面:

@RenderSection("scripts", required: false)

其他回答

section不能在局部视图中工作,这是设计的。您可以使用一些自定义助手来实现类似的行为,但老实说,包含必要的脚本是视图的责任,而不是部分的责任。我建议使用主视图的@scripts部分来实现这一点,而不用担心脚本的部分。

这是一个很常见的问题,所以我会把我的答案贴出来。

我也遇到过同样的问题,虽然它不是理想的,但我认为它实际上工作得很好,并且不使部分依赖于视图。

我的场景是,一个动作本身是可访问的,但也可以嵌入到一个视图中——一个谷歌映射。

在我的_layout中我有:

@RenderSection("body_scripts", false)

在我的索引视图中有:

@Html.Partial("Clients")
@section body_scripts
{
    @Html.Partial("Clients_Scripts")
}

在我的客户视图中,我有(所有的地图和assoc。html):

@section body_scripts
{
    @Html.Partial("Clients_Scripts")
}

我的Clients_Scripts视图包含要呈现到页面上的javascript。

通过这种方式,我的脚本是隔离的,并且可以在需要的地方呈现到页面中,而body_scripts标记只在razor视图引擎第一次发现它时呈现。

这让我把所有东西都分开了——这对我来说是一个很好的解决方案,其他人可能有问题,但它确实修补了“设计”的漏洞。

我有一个类似的问题,我有一个母版页如下:

@section Scripts {
<script>
    $(document).ready(function () {
        ...
    });
</script>
}

...

@Html.Partial("_Charts", Model)

但是部分视图依赖于脚本部分中的一些JavaScript。我通过将部分视图编码为JSON来解决这个问题,将其加载到JavaScript变量中,然后使用它来填充一个div,因此:

@{
    var partial = Html.Raw(Json.Encode(new { html = Html.Partial("_Charts", Model).ToString() }));
}

@section Scripts {
<script>
    $(document).ready(function () {
        ...
        var partial = @partial;
        $('#partial').html(partial.html);
    });
</script>
}

<div id="partial"></div>

好吧,我猜其他海报已经为你提供了一种直接在你的部分中包含@section的方法(通过使用第三方html助手)。

但是,我认为,如果你的脚本是紧密耦合到你的部分,只是把你的javascript直接放在一个内联<script>标签在你的部分,并完成它(只是要小心脚本复制,如果你打算使用部分不止一次在一个视图);

你可以使用这些扩展方法:(保存为PartialWithScript.cs)

namespace System.Web.Mvc.Html
{
    public static class PartialWithScript
    {
        public static void RenderPartialWithScript(this HtmlHelper htmlHelper, string partialViewName)
        {
            if (htmlHelper.ViewBag.ScriptPartials == null)
            {
                htmlHelper.ViewBag.ScriptPartials = new List<string>();
            }

            if (!htmlHelper.ViewBag.ScriptPartials.Contains(partialViewName))
            {
                htmlHelper.ViewBag.ScriptPartials.Add(partialViewName);
            }

            htmlHelper.ViewBag.ScriptPartialHtml = true;
            htmlHelper.RenderPartial(partialViewName);
        }

        public static void RenderPartialScripts(this HtmlHelper htmlHelper)
        {
            if (htmlHelper.ViewBag.ScriptPartials != null)
            {
                htmlHelper.ViewBag.ScriptPartialHtml = false;
                foreach (string partial in htmlHelper.ViewBag.ScriptPartials)
                {
                    htmlHelper.RenderPartial(partial);
                }
            }
        }
    }
}

像这样使用:

示例partial:(_MyPartial.cshtml) 把html放在if里,js放在else里。

@if (ViewBag.ScriptPartialHtml ?? true)
    <p>I has htmls</p>
}
else {
    <script type="text/javascript">
        alert('I has javascripts');
    </script>
}

在你的_Layout中。cshtml,或者任何你想要渲染的部分脚本的地方,放置以下(一次):它将只在当前页面的这个位置渲染所有部分的javascript。

@{ Html.RenderPartialScripts(); }

然后使用您的部分,只需这样做:它将只呈现该位置的html。

@{Html.RenderPartialWithScript("~/Views/MyController/_MyPartial.cshtml");}