首页 文章

从视图或部分视图添加 CSS 或 JavaScript 文件到布局头

提问于
浏览
169

布局页面头:

<head>
    <link href="@Url.Content("~/Content/themes/base/Site.css")"
          rel="stylesheet" type="text/css" />
</head>

应用程序需要的 View(AnotherView):

<link href="@Url.Content("~/Content/themes/base/AnotherPage.css")"
      rel="stylesheet" type="text/css" />

和 AnotherView 有一个局部视图(AnotherPartial)需要:

<link href="@Url.Content("~/Content/themes/base/AnotherPartial.css")"
      rel="stylesheet" type="text/css" />

问题:我们如何添加这些 CSS 文件链接AnotherView 和 AnotherPartial 链接到布局头

RenderSection 不是一个好主意,因为 AnotherPage 可以有多个 Partials。添加所有 CSS 到头部是没用的,因为它将动态更改(它取决于 Anotherpages)。

10 回答

  • 3

    这是一个名为暗盒NuGet插件,除此之外,它还提供了在 partials 中引用脚本和样式的功能。

    虽然这个插件有许多配置可用,但它非常灵活。以下是引用脚本或样式表文件的最简单方法:

    Bundles.Reference("scripts/app");
    

    根据文件

    Reference的调用可以出现在页面,布局或局部视图中的任何位置。

    path 参数可以是以下之一:

    • 捆绑路径

    • 资产路径 - 引用包含此资产的整个捆绑包

    • 一个 URL

  • 193

    布局:

    <html>
        <head>
            <meta charset="utf-8" />
            <title>@ViewBag.Title</title>
            <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
            <script src="@Url.Content("~/Scripts/jquery-1.6.2.min.js")" type="text/javascript"></script>
            <script src="@Url.Content("~/Scripts/modernizr-2.0.6-development-only.js")" type="text/javascript"></script>
            @if (IsSectionDefined("AddToHead"))
            {
                @RenderSection("AddToHead", required: false)
            }
    
            @RenderSection("AddToHeadAnotherWay", required: false)
        </head>
    

    视图:

    @model ProjectsExt.Models.DirectoryObject
    
    @section AddToHead{
        <link href="@Url.Content("~/Content/Upload.css")" rel="stylesheet" type="text/css" />
    }
    
  • 72

    更新https://github.com/speier/mvcassetshelper的基本示例

    我们使用以下实现将 JS 和 CSS 文件添加到布局页面中。

    查看或部分查看:

    @{
        Html.Assets().Styles.Add("/Dashboard/Content/Dashboard.css");
        Html.Assets().Scripts.Add("/Dashboard/Scripts/Dashboard.js");
    }
    

    布局页面:

    <head>
        @Html.Assets().Styles.Render()
    </head>
    
    <body>
        ...
        @Html.Assets().Scripts.Render()
    </body>
    

    HtmlHelper 扩展:

    public static class HtmlHelperExtensions
    {
        public static AssetsHelper Assets(this HtmlHelper htmlHelper)
        {
            return AssetsHelper.GetInstance(htmlHelper);
        }    
    }
    
    public class AssetsHelper 
    {
        public static AssetsHelper GetInstance(HtmlHelper htmlHelper)
        {
            var instanceKey = "AssetsHelperInstance";
    
            var context = htmlHelper.ViewContext.HttpContext;
            if (context == null) return null;
    
            var assetsHelper = (AssetsHelper)context.Items[instanceKey];
    
            if (assetsHelper == null)
                context.Items.Add(instanceKey, assetsHelper = new AssetsHelper());
    
            return assetsHelper;
        }
    
        public ItemRegistrar Styles { get; private set; }
        public ItemRegistrar Scripts { get; private set; }
    
        public AssetsHelper()
        {
            Styles = new ItemRegistrar(ItemRegistrarFormatters.StyleFormat);
            Scripts = new ItemRegistrar(ItemRegistrarFormatters.ScriptFormat);
        }
    }
    
    public class ItemRegistrar
    {
        private readonly string _format;
        private readonly IList<string> _items;
    
        public ItemRegistrar(string format)
        {
            _format = format;
            _items = new List<string>();
        }
    
        public ItemRegistrar Add(string url)
        {
            if (!_items.Contains(url))
                _items.Add(url);
    
            return this;
        }
    
        public IHtmlString Render()
        {
            var sb = new StringBuilder();
    
            foreach (var item in _items)
            {
                var fmt = string.Format(_format, item);
                sb.AppendLine(fmt);
            }
    
            return new HtmlString(sb.ToString());
        }
    }
    
    public class ItemRegistrarFormatters
    {
        public const string StyleFormat = "<link href=\"{0}\" rel=\"stylesheet\" type=\"text/css\" />";
        public const string ScriptFormat = "<script src=\"{0}\" type=\"text/javascript\"></script>";
    }
    
  • 11

    遗憾的是,默认情况下,这不可能像其他用户建议的那样使用section,因为section仅适用于Viewchild

    然而,有效的是在每个视图中实现和重新定义部分,意思是:

    section Head
    {
        @RenderSection("Head", false)
    }
    

    这样每个视图都可以实现头部,而不仅仅是直接的孩子。这只能部分起作用,尤其是多个部分故障开始(正如你在问题中提到的那样)。

    因此,问题的唯一真正解决方案是使用ViewBag。最好的可能是 CSS 和脚本的单独集合(列表)。为此,您需要确保在执行任何视图之前初始化List used。然后,您可以在每个 view/partial 的顶部执行此类操作(如果ScriptsStyles值为 null,则无需关心:

    ViewBag.Scripts.Add("myscript.js");
    ViewBag.Styles.Add("mystyle.css");
    

    在布局中,您可以遍历集合并根据List中的值添加样式。

    @foreach (var script in ViewBag.Scripts)
    {
        <script type="text/javascript" src="@script"></script>
    }
    @foreach (var style in ViewBag.Styles)
    {
        <link href="@style" rel="stylesheet" type="text/css" />
    }
    

    我觉得它很难看,但它是唯一可行的。

    ****UPDATE**因为它首先开始执行内部视图并且正在逐步实现布局并且 CSS 样式是级联的,所以通过ViewBag.Styles.Reverse()反转样式列表可能是有意义的。

    这样就可以首先添加最外层的样式,这与 CSS 样式表的工作方式无关。

  • 9

    您可以在布局中通过 RenderSection 方法定义节。

    布局

    <head>
      <link href="@Url.Content("~/Content/themes/base/Site.css")"
        rel="stylesheet" type="text/css" />
      @RenderSection("heads", required: false)
    </head>
    

    然后,您可以将 css 文件包含在视图中的区域区域除了局部视图

    该部分在视图中工作,但不能在部分视图中按设计工作

    <!--your code -->
    @section heads
    {
      <link href="@Url.Content("~/Content/themes/base/AnotherPage.css")"
      rel="stylesheet" type="text/css" />
    }
    

    如果您确实想在局部视图中使用剖面区域,可以按照文章重新定义 RenderSection 方法。

    剃刀,嵌套布局和重新定义的部分 - Marcin On ASP.NET

  • 5

    我试图解决这个问题。

    我的回答在这里。

    “DynamicHeader” - http://dynamicheader.codeplex.com/https://nuget.org/packages/DynamicHeader

    例如,_Layout.cshtml 是:

    <head>
    @Html.DynamicHeader()
    </head>
    ...
    

    并且,您可以在任何地方将.js 和.css 文件注册到“DynamicHeader”

    例如,AnotherPartial.cshtm 中的代码块是:

    @{
      DynamicHeader.AddSyleSheet("~/Content/themes/base/AnotherPartial.css");
      DynamicHeader.AddScript("~/some/myscript.js");
    }
    

    然后,最终输出 HTML 是:

    <html>
      <link href="/myapp/Content/themes/base/AnotherPartial.css" .../>
      <script src="/myapp/some/myscript.js" ...></script>
    </html>
    ...
    
  • 5

    我有一个类似的问题,最后用下面的代码应用卡尔曼的优秀答案(不是很整洁,但可以说更可扩展):

    namespace MvcHtmlHelpers
    {
        //http://stackoverflow.com/questions/5110028/add-css-or-js-files-to-layout-head-from-views-or-partial-views#5148224
        public static partial class HtmlExtensions
        {
            public static AssetsHelper Assets(this HtmlHelper htmlHelper)
            {
                return AssetsHelper.GetInstance(htmlHelper);
            }
        }
        public enum BrowserType { Ie6=1,Ie7=2,Ie8=4,IeLegacy=7,W3cCompliant=8,All=15}
        public class AssetsHelper
        {
            public static AssetsHelper GetInstance(HtmlHelper htmlHelper)
            {
                var instanceKey = "AssetsHelperInstance";
                var context = htmlHelper.ViewContext.HttpContext;
                if (context == null) {return null;}
                var assetsHelper = (AssetsHelper)context.Items[instanceKey];
                if (assetsHelper == null){context.Items.Add(instanceKey, assetsHelper = new AssetsHelper(htmlHelper));}
                return assetsHelper;
            }
            private readonly List<string> _styleRefs = new List<string>();
            public AssetsHelper AddStyle(string stylesheet)
            {
                _styleRefs.Add(stylesheet);
                return this;
            }
            private readonly List<string> _scriptRefs = new List<string>();
            public AssetsHelper AddScript(string scriptfile)
            {
                _scriptRefs.Add(scriptfile);
                return this;
            }
            public IHtmlString RenderStyles()
            {
                ItemRegistrar styles = new ItemRegistrar(ItemRegistrarFormatters.StyleFormat,_urlHelper);
                styles.Add(Libraries.UsedStyles());
                styles.Add(_styleRefs);
                return styles.Render();
            }
            public IHtmlString RenderScripts()
            {
                ItemRegistrar scripts = new ItemRegistrar(ItemRegistrarFormatters.ScriptFormat, _urlHelper);
                scripts.Add(Libraries.UsedScripts());
                scripts.Add(_scriptRefs);
                return scripts.Render();
            }
            public LibraryRegistrar Libraries { get; private set; }
            private UrlHelper _urlHelper;
            public AssetsHelper(HtmlHelper htmlHelper)
            {
                _urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
                Libraries = new LibraryRegistrar();
            }
        }
        public class LibraryRegistrar
        {
            public class Component
            {
                internal class HtmlReference
                {
                    internal string Url { get; set; }
                    internal BrowserType ServeTo { get; set; }
                }
                internal List<HtmlReference> Styles { get; private set; }
                internal List<HtmlReference> Scripts { get; private set; }
                internal List<string> RequiredLibraries { get; private set; }
    
                public Component()
                {
                    Styles = new List<HtmlReference>();
                    Scripts = new List<HtmlReference>();
                    RequiredLibraries = new List<string>();
                }
                public Component Requires(params string[] libraryNames)
                {
                    foreach (var lib in libraryNames)
                    {
                        if (!RequiredLibraries.Contains(lib))
                            { RequiredLibraries.Add(lib); }
                    }
                    return this;
                }
                public Component AddStyle(string url, BrowserType serveTo = BrowserType.All)
                {
                    Styles.Add(new HtmlReference { Url = url, ServeTo=serveTo });
                    return this;
                }
                public Component AddScript(string url, BrowserType serveTo = BrowserType.All)
                {
                    Scripts.Add(new HtmlReference { Url = url, ServeTo = serveTo });
                    return this;
                }
            }
            private readonly Dictionary<string, Component> _allLibraries = new Dictionary<string, Component>();
            private List<string> _usedLibraries = new List<string>();
            internal IEnumerable<string> UsedScripts()
            {
                SetOrder();
                var returnVal = new List<string>();
                foreach (var key in _usedLibraries)
                {
                    returnVal.AddRange(from s in _allLibraries[key].Scripts
                                       where IncludesCurrentBrowser(s.ServeTo)
                                       select s.Url);
                }
                return returnVal;
            }
            internal IEnumerable<string> UsedStyles()
            {
                SetOrder();
                var returnVal = new List<string>();
                foreach (var key in _usedLibraries)
                {
                    returnVal.AddRange(from s in _allLibraries[key].Styles
                                       where IncludesCurrentBrowser(s.ServeTo)
                                       select s.Url);
                }
                return returnVal;
            }
            public void Uses(params string[] libraryNames)
            {
                foreach (var name in libraryNames)
                {
                    if (!_usedLibraries.Contains(name)){_usedLibraries.Add(name);}
                }
            }
            public bool IsUsing(string libraryName)
            {
                SetOrder();
                return _usedLibraries.Contains(libraryName);
            }
            private List<string> WalkLibraryTree(List<string> libraryNames)
            {
                var returnList = new List<string>(libraryNames);
                int counter = 0;
                foreach (string libraryName in libraryNames)
                {
                    WalkLibraryTree(libraryName, ref returnList, ref counter);
                }
                return returnList;
            }
            private void WalkLibraryTree(string libraryName, ref List<string> libBuild, ref int counter)
            {
                if (counter++ > 1000) { throw new System.Exception("Dependancy library appears to be in infinate loop - please check for circular reference"); }
                Component library;
                if (!_allLibraries.TryGetValue(libraryName, out library))
                    { throw new KeyNotFoundException("Cannot find a definition for the required style/script library named: " + libraryName); }
                foreach (var childLibraryName in library.RequiredLibraries)
                {
                    int childIndex = libBuild.IndexOf(childLibraryName);
                    if (childIndex!=-1)
                    {
                        //child already exists, so move parent to position before child if it isn't before already
                        int parentIndex = libBuild.LastIndexOf(libraryName);
                        if (parentIndex>childIndex)
                        {
                            libBuild.RemoveAt(parentIndex);
                            libBuild.Insert(childIndex, libraryName);
                        }
                    }
                    else
                    {
                        libBuild.Add(childLibraryName);
                        WalkLibraryTree(childLibraryName, ref libBuild, ref counter);
                    }
                }
                return;
            }
            private bool _dependenciesExpanded;
            private void SetOrder()
            {
                if (_dependenciesExpanded){return;}
                _usedLibraries = WalkLibraryTree(_usedLibraries);
                _usedLibraries.Reverse();
                _dependenciesExpanded = true;
            }
            public Component this[string index]
            {
                get
                {
                    if (_allLibraries.ContainsKey(index))
                        { return _allLibraries[index]; }
                    var newComponent = new Component();
                    _allLibraries.Add(index, newComponent);
                    return newComponent;
                }
            }
            private BrowserType _requestingBrowser;
            private BrowserType RequestingBrowser
            {
                get
                {
                    if (_requestingBrowser == 0)
                    {
                        var browser = HttpContext.Current.Request.Browser.Type;
                        if (browser.Length > 2 && browser.Substring(0, 2) == "IE")
                        {
                            switch (browser[2])
                            {
                                case '6':
                                    _requestingBrowser = BrowserType.Ie6;
                                    break;
                                case '7':
                                    _requestingBrowser = BrowserType.Ie7;
                                    break;
                                case '8':
                                    _requestingBrowser = BrowserType.Ie8;
                                    break;
                                default:
                                    _requestingBrowser = BrowserType.W3cCompliant;
                                    break;
                            }
                        }
                        else
                        {
                            _requestingBrowser = BrowserType.W3cCompliant;
                        }
                    }
                    return _requestingBrowser;
                }
            }
            private bool IncludesCurrentBrowser(BrowserType browserType)
            {
                if (browserType == BrowserType.All) { return true; }
                return (browserType & RequestingBrowser) != 0;
            }
        }
        public class ItemRegistrar
        {
            private readonly string _format;
            private readonly List<string> _items;
            private readonly UrlHelper _urlHelper;
    
            public ItemRegistrar(string format, UrlHelper urlHelper)
            {
                _format = format;
                _items = new List<string>();
                _urlHelper = urlHelper;
            }
            internal void Add(IEnumerable<string> urls)
            {
                foreach (string url in urls)
                {
                    Add(url);
                }
            }
            public ItemRegistrar Add(string url)
            {
                url = _urlHelper.Content(url);
                if (!_items.Contains(url))
                    { _items.Add( url); }
                return this;
            }
            public IHtmlString Render()
            {
                var sb = new StringBuilder();
                foreach (var item in _items)
                {
                    var fmt = string.Format(_format, item);
                    sb.AppendLine(fmt);
                }
                return new HtmlString(sb.ToString());
            }
        }
        public class ItemRegistrarFormatters
        {
            public const string StyleFormat = "<link href=\"{0}\" rel=\"stylesheet\" type=\"text/css\" />";
            public const string ScriptFormat = "<script src=\"{0}\" type=\"text/javascript\"></script>";
        }
    }
    

    该项目包含一个静态 AssignAllResources 方法:

    assets.Libraries["jQuery"]
            .AddScript("~/Scripts/jquery-1.10.0.min.js", BrowserType.IeLegacy)
            .AddScript("~/Scripts//jquery-2.0.1.min.js",BrowserType.W3cCompliant);
            /* NOT HOSTED YET - CHECK SOON 
            .AddScript("//ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js",BrowserType.W3cCompliant);
            */
        assets.Libraries["jQueryUI"].Requires("jQuery")
            .AddScript("//ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js",BrowserType.Ie6)
            .AddStyle("//ajax.aspnetcdn.com/ajax/jquery.ui/1.9.2/themes/eggplant/jquery-ui.css",BrowserType.Ie6)
            .AddScript("//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js", ~BrowserType.Ie6)
            .AddStyle("//ajax.aspnetcdn.com/ajax/jquery.ui/1.10.3/themes/eggplant/jquery-ui.css", ~BrowserType.Ie6);
        assets.Libraries["TimePicker"].Requires("jQueryUI")
            .AddScript("~/Scripts/jquery-ui-sliderAccess.min.js")
            .AddScript("~/Scripts/jquery-ui-timepicker-addon-1.3.min.js")
            .AddStyle("~/Content/jQueryUI/jquery-ui-timepicker-addon.css");
        assets.Libraries["Validation"].Requires("jQuery")
            .AddScript("//ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js")
            .AddScript("~/Scripts/jquery.validate.unobtrusive.min.js")
            .AddScript("~/Scripts/mvcfoolproof.unobtrusive.min.js")
            .AddScript("~/Scripts/CustomClientValidation-1.0.0.min.js");
        assets.Libraries["MyUtilityScripts"].Requires("jQuery")
            .AddScript("~/Scripts/GeneralOnLoad-1.0.0.min.js");
        assets.Libraries["FormTools"].Requires("Validation", "MyUtilityScripts");
        assets.Libraries["AjaxFormTools"].Requires("FormTools", "jQueryUI")
            .AddScript("~/Scripts/jquery.unobtrusive-ajax.min.js");
        assets.Libraries["DataTables"].Requires("MyUtilityScripts")
            .AddScript("//ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js")
            .AddStyle("//ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables.css")
            .AddStyle("//ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables_themeroller.css");
        assets.Libraries["MvcDataTables"].Requires("DataTables", "jQueryUI")
            .AddScript("~/Scripts/jquery.dataTables.columnFilter.min.js");
        assets.Libraries["DummyData"].Requires("MyUtilityScripts")
            .AddScript("~/Scripts/DummyData.js")
            .AddStyle("~/Content/DummyData.css");
    

    在_layout 页面

    @{
        var assets = Html.Assets();
        CurrentResources.AssignAllResources(assets);
        Html.Assets().RenderStyles()
    }
    </head>
    ...
        @Html.Assets().RenderScripts()
    </body>
    

    并在 partial(s)和观点

    Html.Assets().Libraries.Uses("DataTables");
    Html.Assets().AddScript("~/Scripts/emailGridUtilities.js");
    
  • 4

    尝试 out-of-the-box 解决方案(ASP.NET MVC 4 或更高版本):

    @{
        var bundle = BundleTable.Bundles.GetRegisteredBundles().First(b => b.Path == "~/js");
    
        bundle.Include("~/Scripts/myFile.js");
    }
    
  • 4

    对于我们这些使用 ASP.NET MVC 4 的人来说 - 这可能会有所帮助。

    首先,我在 App_Start 文件夹中添加了一个 BundleConfig 类。

    这是我用来创建它的代码:

    using System.Web.Optimization;
    
    public class BundleConfig
    {
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/SiteMaster.css"));
        }
    }
    

    其次,我在 Global.asax 文件中注册了 BundleConfig 类:

    protected void Application_Start()
    {
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
    

    第三,我在我的 CSS 文件中添加了样式助手:

    /* Styles for validation helpers */
    .field-validation-error {
        color: red;
        font-weight: bold;
    }
    
    .field-validation-valid {
        display: none;
    }
    
    input.input-validation-error {
        border: 1px solid #e80c4d;
    }
    
    input[type="checkbox"].input-validation-error {
        border: 0 none;
    }
    
    .validation-summary-errors {
        color: #e80c4d;
        font-weight: bold;
        font-size: 1.1em;
    }
    
    .validation-summary-valid {
        display: none;
    }
    

    最后我在任何视图中使用了这种语法:

    @Styles.Render("~/Content/css")
    
  • 2

    我写了一个简单的包装器,允许您在每个局部视图中动态地将样式和描述注册到 head 标签中。

    它基于 DynamicHeader jsakamoto 提出,但它有一些性能改进和调整。

    它非常易于使用,而且功能多样。

    用法:

    @{
        DynamicHeader.AddStyleSheet("/Content/Css/footer.css", ResourceType.Layout);    
        DynamicHeader.AddStyleSheet("/Content/Css/controls.css", ResourceType.Infrastructure);
        DynamicHeader.AddScript("/Content/Js/Controls.js", ResourceType.Infrastructure);
        DynamicHeader.AddStyleSheet("/Content/Css/homepage.css");    
    }
    

    你可以在里面找到完整的代码,解释和例子:动态添加样式和脚本到标记

相关问题