Помощник по регистрации скриптов и CSS в ASP.NET MVC?

Некоторое время я пытался использовать ASP.NET MVC, а затем столкнулся с проблемой, заключающейся в том, что я не хочу включать все свои js и css в главную страницу. Но как я могу зарегистрировать его в заголовке главной страницы из моего конкретного просмотра?

8 ответов

Решение

Шаблон главной страницы по умолчанию включает в себя ContentHolder для заголовка. Если это не так, вы можете легко добавить один:

<head runat="server">
    <title></title>
    <asp:ContentPlaceHolder ID="head" runat="server" />
</head>

Ваши взгляды могут тогда поместить все, что они хотят в голову:

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
    <script src="Scripts/myScripts.js" type="text/javascript"></script>
    <link href="Styles/myStyles.css" rel="stylesheet" type="text/css" />
</asp:Content>

Похоже, что пока нет простой опции "встроенной" в инфраструктуру ASP.NET MVC. Если вы используете пользовательский элемент управления (.ascx), которым вы можете быть, если вы создаете автономные элементы управления, которые также хотят управлять своими собственными требованиями JavaScript, тогда вы даже не сможете использовать заполнители, чтобы помочь вам.

В конце я создал вспомогательный класс и в нем есть пара методов:

private static SortedList<int, string> GetRegisteredScriptIncludes()
{
    var registeredScriptIncludes = System.Web.HttpContext.Current.Items["RegisteredScriptIncludes"] as SortedList<int, string>;

    if (registeredScriptIncludes == null)
    {
        registeredScriptIncludes = new SortedList<int, string>();
        System.Web.HttpContext.Current.Items["RegisteredScriptIncludes"] = registeredScriptIncludes;
    }

    return registeredScriptIncludes;
}

public static void RegisterScriptInclude(this HtmlHelper htmlhelper, string script)
{
    var registeredScriptIncludes = GetRegisteredScriptIncludes();
    if (!registeredScriptIncludes.ContainsValue(script))
    {
        registeredScriptIncludes.Add(registeredScriptIncludes.Count, script);
    }
}

public static string RenderScripts(this HtmlHelper htmlhelper)
{
    var registeredScriptIncludes = GetRegisteredScriptIncludes();
    var scripts = new StringBuilder();
    foreach (string script in registeredScriptIncludes.Values)
    {
        scripts.AppendLine("<script src='" + script + "' type='text/javascript'></script>");
    }
    return scripts.ToString();
}

В любом случае, это основная форма, чтобы попытаться показать, как это работает. Его можно улучшить многими способами, но в данный момент он просто отфильтровывает дубликаты запросов на вставку скрипта для вас. Всякий раз, когда вы хотите добавить новый скрипт в ascx (или aspx в этом отношении), вы можете сделать это следующим образом:

<%
    Html.RegisterScriptInclude(Url.Content("~/Scripts/MapLayers/MapLayer.js"));
    Html.RegisterScriptInclude(Url.Content("~/Scripts/MapLayers/Vehicles.js"));
%>

Затем вы должны помнить, чтобы вывести их, как только вы закончите. Это достигается с помощью следующего вызова в том месте на вашей странице, где вы хотите вывести теги сценария:

<%=Html.RenderScripts() %>

Кажется, до сих пор работает для меня. Я почти ожидал, что возникнут проблемы с рендерингом, в зависимости от того, в какой момент был вызван RenderScripts, особенно если не все из RegisterScriptInclude были вызваны, но пока, похоже, это делает свою работу. Если вы делаете сценарии последними, у вас не должно быть проблем.

@Jason: ВНИМАНИЕ, вы не должны использовать статические переменные, подобные этой... В веб-контексте статические переменные являются общими для всех пользователей и всех запросов страниц. Я поражен, что у вас не было проблем с вашим кодом. Принцип в порядке, но код неверен и доставит вам неприятности. В этом случае вы должны использовать System.Web.HttpContext.Current.Items. См. http://www.hanselman.com/blog/ATaleOfTwoTechniquesTheThreadStaticAttributeAndSystemWebHttpContextCurrentItems.aspx для получения дополнительной информации.

Вот решение, подобное тому, которое дал Джейсон, но учитывает комментарии vdh_ant:

http://frugalcoder.us/post/2009/06/29/Handling-Scripts-in-ASPNet-MVC.aspx

Я написал именно такого менеджера для MVC и написал об этом в своем блоге:

"JavascriptHelper – Управление файлами JS для ASP.NET MVC"

ОБНОВЛЕНИЕ: я добавил пакет: "JavascriptHelper: Управление файлами JS для ASP.NET MVC (с комплектацией)"

MVC Futures теперь имеет встроенных помощников для этого...

1.<head>
2.    <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
3.    <%= Html.Css("BlueTheme/site.css") %>
4.    <%= Html.Script("jquery-1.3.2.js") %>
5.</head>

Более подробная информация здесь: http://blog.osbornm.com/archive/2009/10/12/mvc-script-css-helpers.aspx

Технически вы должны поместить все свои js внизу страницы для лучшей производительности.

Однако я думаю, что единственный способ сделать это - включить JavaScript в VIewData и отобразить ViewData на главной странице (не очень хорошее решение).

Mathew,

Я взглянул на ваш блог о помощниках Html.Css и Html.Script. Я не хочу быть критичным, но я не вижу упоминаний в блоге о том, как помощники Css и Script решат проблему, обсуждаемую здесь. Проблема здесь заключается в необходимости "регистрировать" ссылки на скрипты в любой точке во время процесса рендеринга и, возможно, несколько раз (в случае шаблона или частичного представления, которое используется несколько раз и регистрирует свои собственные скрипты), а затем выводить совокупные результаты без дубликатов в одном месте.

Если ваше решение решает эту проблему, пожалуйста, исправьте меня с некоторыми разъяснениями.

--Regards, Кен

Другие вопросы по тегам