我在我的_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视图中注入一些内容。

我该怎么做呢?


当前回答

我们看待网络的方式有一个根本性的缺陷,尤其是在使用MVC的时候。缺陷在于JavaScript在某种程度上是视图的责任。视图是视图,JavaScript(行为或其他)是JavaScript。在Silverlight和WPF的MVVM模式中,我们面临着“视图优先”或“模型优先”的问题。在MVC中,我们应该总是尝试从模型的角度进行推理,而JavaScript在很多方面都是这个模型的一部分。

我建议使用AMD模式(我自己喜欢RequireJS)。在模块中分离你的JavaScript,定义你的功能,从JavaScript中钩子到你的html,而不是依赖于一个视图来加载JavaScript。这将清理您的代码,分离您的关注点,并使生活变得更简单。

其他回答

我能想到的第一个解决方案是使用ViewBag来存储必须呈现的值。

我从来没有试过,如果这个工作从一个局部的观点,但它应该在我看来。

遵循不引人注目的原则,“_myPartial”并不完全需要将内容直接注入脚本部分。您可以将这些部分视图脚本添加到单独的.js文件中,并从父视图中将它们引用到@scripts部分。

使用Mvc Core,你可以创建一个整洁的TagHelper脚本,如下所示。这可以很容易地转换成一个节标记,在这里您也可以给它一个名称(或者名称取自派生类型)。注意,需要为IHttpContextAccessor设置依赖注入。

当添加脚本时(例如在部分中)

<scripts>
    <script type="text/javascript">
        //anything here
    </script>
</scripts>

当输出脚本时(例如在一个布局文件中)

<scripts render="true"></scripts>

Code

public class ScriptsTagHelper : TagHelper
    {
        private static readonly object ITEMSKEY = new Object();

        private IDictionary<object, object> _items => _httpContextAccessor?.HttpContext?.Items;

        private IHttpContextAccessor _httpContextAccessor;

        public ScriptsTagHelper(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            var attribute = (TagHelperAttribute)null;
            context.AllAttributes.TryGetAttribute("render",out attribute);

            var render = false;

            if(attribute != null)
            {
                render = Convert.ToBoolean(attribute.Value.ToString());
            }

            if (render)
            {
                if (_items.ContainsKey(ITEMSKEY))
                {
                    var scripts = _items[ITEMSKEY] as List<HtmlString>;

                    var content = String.Concat(scripts);

                    output.Content.SetHtmlContent(content);
                }
            }
            else
            {
                List<HtmlString> list = null;

                if (!_items.ContainsKey(ITEMSKEY))
                {
                    list = new List<HtmlString>();
                    _items[ITEMSKEY] = list;
                }

                list = _items[ITEMSKEY] as List<HtmlString>;

                var content = await output.GetChildContentAsync();

                list.Add(new HtmlString(content.GetContent()));
            }
        }
    }

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

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

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

在我的_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视图引擎第一次发现它时呈现。

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

我们看待网络的方式有一个根本性的缺陷,尤其是在使用MVC的时候。缺陷在于JavaScript在某种程度上是视图的责任。视图是视图,JavaScript(行为或其他)是JavaScript。在Silverlight和WPF的MVVM模式中,我们面临着“视图优先”或“模型优先”的问题。在MVC中,我们应该总是尝试从模型的角度进行推理,而JavaScript在很多方面都是这个模型的一部分。

我建议使用AMD模式(我自己喜欢RequireJS)。在模块中分离你的JavaScript,定义你的功能,从JavaScript中钩子到你的html,而不是依赖于一个视图来加载JavaScript。这将清理您的代码,分离您的关注点,并使生活变得更简单。