working section scripts script not javascript asp.net-mvc-3 razor

javascript - section - Rellenar una sección de maquinilla de afeitar de un parcial



@section scripts not working in partial view (11)

Mi motivación principal para tratar de hacer esto es obtener Javascript que solo es requerido por un parcial en la parte inferior de la página con el resto del Javascript y no en el medio de la página donde se representa el parcial.

Aquí hay un ejemplo simplificado de lo que estoy tratando de hacer:

Aquí está el diseño con una sección de Scripts justo antes del cuerpo.

<!DOCTYPE html> <html> <head> <title>@ViewBag.Title</title> <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" /> </head> <body> @RenderBody() <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script> @RenderSection("Scripts", false) </body> </html>

Aquí hay una vista de ejemplo usando este diseño.

<h2>This is the view</h2> @{Html.RenderPartial("_Partial");} @section Scripts { <script type="text/javascript"> alert("I''m a view."); </script> }

Y aquí está el renderizado parcial de la vista.

<p>This is the partial.</p> @* this never makes it into the rendered page *@ @section Scripts { <script type="text/javascript"> alert("I''m a partial."); </script> }

En este ejemplo, el marcado especificado en la vista se coloca en la sección, pero el marcado del parcial no. ¿Es posible completar una sección desde una vista parcial con Razor? Si no es así, ¿cuáles son algunos otros métodos para obtener Javascript que solo necesitan los parciales en la parte inferior de la página sin incluirlo globalmente?


Aquí aparece mi solución a las preguntas más frecuentes "¿cómo inyectar secciones desde vistas parciales a vistas principales o vista de diseño principal para asp.net mvc?". Si haces una búsqueda en por palabras clave "sección + parcial", obtendrás una lista bastante grande de preguntas relacionadas, y respuestas dadas, pero ninguna de ellas me parece elegante por medio de la gramática de la máquina de afeitar. Así que solo eché un vistazo al motor Razor para ver si podría haber una solución mejor para esta pregunta.

Afortunadamente, encontré algo interesante para mí sobre cómo el motor Razor hace la compilación para el archivo de plantilla de vista (* .cshtml, * .vbhtml). (Explicaré más adelante), a continuación se muestra mi código de la solución, que creo que es bastante simple y bastante elegante en su uso.

namespace System.Web.Mvc.Html { public static class HtmlHelperExtensions { /// <summary> /// 确保所有视图,包括分部视图(PartialView)中的节(Section)定义被按照先后顺序追加到最终文档输出流中 /// </summary> public static MvcHtmlString EnsureSection(this HtmlHelper helper) { var wp = (WebViewPage)helper.ViewDataContainer; Dictionary<string, WebPages.SectionWriter> sw = (Dictionary<string, WebPages.SectionWriter>)typeof(WebPages.WebPageBase).GetProperty("SectionWriters", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance).GetValue(wp); if (!helper.ViewContext.HttpContext.Items.Contains("SectionWriter")) { Dictionary<string, Stack<WebPages.SectionWriter>> qss = new Dictionary<string, Stack<WebPages.SectionWriter>>(); helper.ViewContext.HttpContext.Items["SectionWriter"] = qss; } var eqs = (Dictionary<string, Stack<WebPages.SectionWriter>>)helper.ViewContext.HttpContext.Items["SectionWriter"]; foreach (var kp in sw) { if (!eqs.ContainsKey(kp.Key)) eqs[kp.Key] = new Stack<WebPages.SectionWriter>(); eqs[kp.Key].Push(kp.Value); } return MvcHtmlString.Create(""); } /// <summary> /// 在文档流中渲染指定的节(Section) /// </summary> public static MvcHtmlString RenderSectionEx(this HtmlHelper helper, string section, bool required = false) { if (helper.ViewContext.HttpContext.Items.Contains("SectionWriter")) { Dictionary<string, Stack<WebPages.SectionWriter>> qss = (Dictionary<string, Stack<WebPages.SectionWriter>>)helper.ViewContext.HttpContext.Items["SectionWriter"]; if (qss.ContainsKey(section)) { var wp = (WebViewPage)helper.ViewDataContainer; var qs = qss[section]; while (qs.Count > 0) { var sw = qs.Pop(); var os = ((WebViewPage)sw.Target).OutputStack; if (os.Count == 0) os.Push(wp.Output); sw.Invoke(); } } else if (!qss.ContainsKey(section) && required) { throw new Exception(string.Format("''{0}'' section is not defined.", section)); } } return MvcHtmlString.Create(""); } } }

uso : para usar el código es bastante simple también, y se ve casi el mismo estilo que el habitual. También admite cualquier nivel para las vistas parciales anidadas. es decir. Tengo una cadena de plantillas de vista: _ViewStart.cshtml-> layout.cshtml-> index.cshtml -> [head.cshtml, foot.cshtml] -> ad.cshtml.

En layout.cshtml, tenemos:

<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>@ViewBag.Title - @ViewBag.WebSetting.Site.WebName</title> <base href="@ViewBag.Template/" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="Cache-Control" content="no-siteapp" /> <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1.0, user-scalable=0,user-scalable=no"> <meta name="format-detection" content="telephone=no"> <meta name="renderer" content="webkit"> <meta name="author" content="Taro Technology Co.,LTD" /> <meta name="robots" content="index,follow" /> <meta name="description" content="" /> <meta name="keywords" content="" /> <link rel="alternate icon" type="@ViewBag.WebSetting.Site.WebFavIcon" href="@ViewBag.WebSetting.Site.WebFavIcon"> @Html.RenderSectionEx("Head") </head> <body> @RenderBody() @Html.RenderSectionEx("Foot") </body> </html>

Y en index.cshtml, tenemos:

@{ ViewBag.Title = "首页"; } @Html.Partial("head") <div class="am-container-1"> ....... </div> @Html.Partial("foot")

Y en head.cshtml, tendríamos el código:

@section Head{ <link rel="stylesheet" href="assets/css/amazeui.css" /> <link rel="stylesheet" href="assets/css/style.css" /> } <header class="header"> ...... </header> @Html.EnsureSection()

es lo mismo en foot.cshtml o ad.cshtml, aún puede definir la sección Head o Foot en ellos, asegúrese de llamar a @ Html.EnsureSection () una vez al final del archivo de vista parcial. Eso es todo lo que necesitas hacer para deshacerte del problema en asp mvc.

Solo comparto mi fragmento de código para que otros puedan usarlo. Si crees que es útil, no dudes en calificar mi publicación. :)


Basándome en la respuesta del Sr. Bell And Shimmy anterior, agrego una función adicional para el script Bundle.

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Text; using System.Web.Mvc; namespace ABC.Utility { public static class PartialViewHelper { public static string RequireScript(this HtmlHelper html, string path, int priority = 1) { var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>; if (requiredScripts == null) HttpContext.Current.Items["RequiredScripts"] = requiredScripts = new List<ResourceInclude>(); if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority }); return null; } public static string RequireBundleStyles(this HtmlHelper html, string bundleName) { var a = System.Web.Optimization.Styles.Render(bundleName); var requiredStyles = HttpContext.Current.Items["RequiredStyles"] as IHtmlString; if (requiredStyles == null) HttpContext.Current.Items["RequiredStyles"] = requiredStyles = a; return null; } public static string RequireBundleScripts(this HtmlHelper html, string bundleName) { var a=System.Web.Optimization.Scripts.Render(bundleName); var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as IHtmlString; if (requiredScripts == null) HttpContext.Current.Items["RequiredScripts"] = requiredScripts = a; return null; } public static HtmlString EmitRequiredBundleStyles(this HtmlHelper html) { var requiredStyles = HttpContext.Current.Items["RequiredStyles"] as IHtmlString; if (requiredStyles == null) return null; return MvcHtmlString.Create(requiredStyles.ToHtmlString()) ; } public static HtmlString EmitRequiredBundleScripts(this HtmlHelper html) { var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as IHtmlString; if (requiredScripts == null) return null; return MvcHtmlString.Create(requiredScripts.ToHtmlString()); } public static HtmlString EmitRequiredScripts(this HtmlHelper html) { var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>; if (requiredScripts == null) return null; StringBuilder sb = new StringBuilder(); foreach (var item in requiredScripts.OrderByDescending(i => i.Priority)) { sb.AppendFormat("<script src=/"{0}/" type=/"text/javascript/"></script>/n", item.Path); } return new HtmlString(sb.ToString()); } public class ResourceInclude { public string Path { get; set; } public int Priority { get; set; } } }//end class }// end namespace

Ejemplo en PartialView: - @ Html.RequireBundleStyles ("~ / bundles / fileupload / bootstrap / BasicPlusUI / css"); @ Html.RequireBundleScripts ("~ / bundles / fileupload / bootstrap / BasicPlusUI / js");

Muestra en MasterPage: - @ Html.EmitRequiredBundleStyles ()


Esta funcionalidad también se implementa en ClientDependency.Core.Mvc.dll. Proporciona los helpers html: @ Html.RequiresJs y @ Html.RenderJsHere (). Paquete Nuget: ClientDependency-Mvc


Instale el paquete Forloop.HtmlHelpers Forloop.HtmlHelpers: agrega algunos ayudantes para administrar scripts en vistas parciales y plantillas de editor.

En algún lugar de su diseño, debe llamar

@Html.RenderScripts()

Aquí será donde se generarán los archivos de script y los bloques de scripts en la página, por lo que recomendaría ponerlos después de los scripts principales en el diseño y después de una sección de scripts (si tiene uno).

Si está utilizando The Web Optimization Framework con bundling, puede usar la sobrecarga

@Html.RenderScripts(Scripts.Render)

para que este método se use para escribir los archivos de script.

Ahora, cada vez que desee agregar bloques de comandos o bloques en una vista, vista parcial o plantilla, simplemente use

@using (Html.BeginScriptContext()) { Html.AddScriptFile("~/Scripts/jquery.validate.js"); Html.AddScriptBlock( @<script type="text/javascript"> $(function() { $(''#someField'').datepicker(); }); </script> ); }

Los ayudantes garantizan que solo se represente una referencia de archivo de script si se agrega varias veces y también garantiza que los archivos de script se procesen en un orden esperado, es decir,

  1. Diseño
  2. Parciales y plantillas (en el orden en que aparecen en la vista, de arriba a abajo)

La forma en que lidié con esto es escribir un par de métodos de extensión para la clase HtmlHelper. Eso permite que las vistas de parciales digan que requieren una secuencia de comandos, y luego en la vista de diseño que escribe la etiqueta que llamo a mi método de ayuda para emitir las secuencias de comandos necesarias.

Aquí están los métodos de ayuda:

public static string RequireScript(this HtmlHelper html, string path, int priority = 1) { var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>; if (requiredScripts == null) HttpContext.Current.Items["RequiredScripts"] = requiredScripts = new List<ResourceInclude>(); if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority }); return null; } public static HtmlString EmitRequiredScripts(this HtmlHelper html) { var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>; if (requiredScripts == null) return null; StringBuilder sb = new StringBuilder(); foreach (var item in requiredScripts.OrderByDescending(i => i.Priority)) { sb.AppendFormat("<script src=/"{0}/" type=/"text/javascript/"></script>/n", item.Path); } return new HtmlString(sb.ToString()); } public class ResourceInclude { public string Path { get; set; } public int Priority { get; set; } }

Una vez que tenga eso en su lugar, su vista parcial solo necesita llamar a @Html.RequireScript("/Path/To/Script") .

Y en la sección principal de la vista de diseño, usted llama a @Html.EmitRequiredScripts() .

Una ventaja adicional de esto es que le permite eliminar las solicitudes de script duplicadas. Si tiene varias vistas / vistas parciales que necesitan una secuencia de comandos determinada, puede suponer con seguridad que solo obtendrá una vez.


La forma más elegante de hacerlo es mover los scripts de vistas parciales a archivos separados y luego renderizarlos en la sección de vista Scripts:

<h2>This is the view</h2> @Html.RenderPartial("_Partial") @section Scripts { @Html.RenderPartial("_PartialScripts") <script type="text/javascript"> alert("I''m a view script."); </script> }

La vista parcial _ Partial.cshtml :

<p>This is the partial.</p>

La vista parcial _ PartialScripts.cshtml solo con scripts:

<script type="text/javascript"> alert("I''m a partial script!"); </script>


Las vistas parciales no pueden participar en las secciones de vistas principales.


Podrías tener un segundo parcial que solo está a cargo de inyectar el javascript necesario. Coloque varios scripts allí alrededor de bloques @if , si lo desea:

@model string @if(Model == "bla") { <script type="text/javascript">...</script> } @else if(Model == "bli") { <script type="text/javascript">...</script> }

Obviamente, esto podría limpiarse un poco, pero luego, en la sección Scripts de su vista:

@section Scripts { @Html.Partial("_Scripts", "ScriptName_For_Partial1") }

Nuevamente, podría no ganar un premio de belleza, pero funcionará.


Puede crear una nueva página de Layout y ajustar el Vista parcial dentro de una Vista completa que es responsable de representar los contenidos y también cualquier sección de la biblioteca.

Por ejemplo, digamos que tengo el siguiente código:

HomeController.cs

[HttpGet] public ActionResult About() { var vm = new AboutViewModel(); return View("About", vm); }

Cuando se muestra la vista de página completa, normalmente se genera fusionando dos archivos:

About.cshtml

@model AboutViewModel @{ ViewBag.Title = "About CSHN"; } <h3>@ViewBag.Title</h3> @section Styles { <style> /* style info here */ </style> } @section Scripts { <script> /* script info here */ </script> }

_Layout.cshtml (o lo que se especifique en _ViewStart o anulado en la página)

<!DOCTYPE html> <html> <head> @RenderSection("Styles", false) <title>@ViewBag.Title</title> </head> <body> @RenderBody() @RenderSection("scripts", false) </body> </html>

Ahora , supongamos que desea Renderizar About.cshtml como una Vista parcial , tal vez como una ventana modal en respuesta a una llamada AJAX. El objetivo aquí es devolver solo el contenido especificado en la página, las secuencias de comandos y todo lo demás, sin todo el engorro incluido en el _Layout.cshtml principal _Layout.cshtml (como un documento <html> completo).

Puede intentarlo así, pero no vendrá con ninguno de los bloques de sección:

return PartialView("About", vm);

En su lugar, agregue una página de diseño más simple como esta:

_PartialLayout.cshtml

<div> @RenderBody() @RenderSection("Styles", false) @RenderSection("scripts", false) </div>

O para admitir una ventana modal como esta:

_ModalLayout.cshtml

<div class="modal modal-page fade" tabindex="-1" role="dialog" > <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <h4 class="modal-title">@ViewBag.Title</h4> </div> <div class="modal-body"> @RenderBody() @RenderSection("Styles", false) @RenderSection("scripts", false) </div> <div class="modal-footer"> <button type="button" class="btn btn-inverse" data-dismiss="modal">Dismiss</button> </div> </div> </div> </div>

A continuación, puede especificar una vista maestra personalizada en este controlador o cualquier otro controlador que desee representar simultáneamente los contenidos y los scripts de una vista

[HttpGet] public ActionResult About() { var vm = new AboutViewModel(); return !Request.IsAjaxRequest() ? View("About", vm) : View("About", "~/Views/Shared/_ModalLayout.cshtml", vm); }


Utilice @using(Html.Delayed()){ ...your content... } extensiones de la respuesta https://.com/a/18790222/1037948 para representar cualquier contenido (scripts o simplemente HTML) más adelante en la página . La Queue interna debe garantizar el orden correcto.


[Versión actualizada] Versión actualizada siguiendo la pregunta @Necrocubus para Incluir scripts en línea.

public static class ScriptsExtensions { const string REQ_SCRIPT = "RequiredScript"; const string REQ_INLINESCRIPT = "RequiredInlineScript"; const string REQ_STYLE = "RequiredStyle"; #region Scripts /// <summary> /// Adds a script /// </summary> /// <param name="html"></param> /// <param name="path"></param> /// <param name="priority">Ordered by decreasing priority </param> /// <param name="bottom"></param> /// <param name="options"></param> /// <returns></returns> public static string RequireScript(this IHtmlHelper html, string path, int priority = 1, bool bottom=false, params string[] options) { var ctxt = html.ViewContext.HttpContext; var requiredScripts = ctxt.Items[REQ_SCRIPT] as List<ResourceToInclude>; if (requiredScripts == null) ctxt.Items[REQ_SCRIPT] = requiredScripts = new List<ResourceToInclude>(); if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceToInclude() { Path = path, Priority = priority, Options = options, Type=ResourceType.Script, Bottom=bottom}); return null; } /// <summary> /// /// </summary> /// <param name="html"></param> /// <param name="script"></param> /// <param name="priority">Ordered by decreasing priority </param> /// <param name="bottom"></param> /// <returns></returns> public static string RequireInlineScript(this IHtmlHelper html, string script, int priority = 1, bool bottom = false) { var ctxt = html.ViewContext.HttpContext; var requiredScripts = ctxt.Items[REQ_INLINESCRIPT] as List<InlineResource>; if (requiredScripts == null) ctxt.Items[REQ_INLINESCRIPT] = requiredScripts = new List<InlineResource>(); requiredScripts.Add(new InlineResource() { Content=script, Priority = priority, Bottom=bottom, Type=ResourceType.Script}); return null; } /// <summary> /// Just call @Html.EmitRequiredScripts(false) /// at the end of your head tag and /// @Html.EmitRequiredScripts(true) at the end of the body if some scripts are set to be at the bottom. /// </summary> public static HtmlString EmitRequiredScripts(this IHtmlHelper html, bool bottom) { var ctxt = html.ViewContext.HttpContext; var requiredScripts = ctxt.Items[REQ_SCRIPT] as List<ResourceToInclude>; var requiredInlineScripts = ctxt.Items[REQ_INLINESCRIPT] as List<InlineResource>; var scripts = new List<Resource>(); scripts.AddRange(requiredScripts ?? new List<ResourceToInclude>()); scripts.AddRange(requiredInlineScripts ?? new List<InlineResource>()); if (scripts.Count==0) return null; StringBuilder sb = new StringBuilder(); foreach (var item in scripts.Where(s=>s.Bottom==bottom).OrderByDescending(i => i.Priority)) { sb.Append(item.ToString()); } return new HtmlString(sb.ToString()); } #endregion Scripts #region Styles /// <summary> /// /// </summary> /// <param name="html"></param> /// <param name="path"></param> /// <param name="priority">Ordered by decreasing priority </param> /// <param name="options"></param> /// <returns></returns> public static string RequireStyle(this IHtmlHelper html, string path, int priority = 1, params string[] options) { var ctxt = html.ViewContext.HttpContext; var requiredScripts = ctxt.Items[REQ_STYLE] as List<ResourceToInclude>; if (requiredScripts == null) ctxt.Items[REQ_STYLE] = requiredScripts = new List<ResourceToInclude>(); if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceToInclude() { Path = path, Priority = priority, Options = options }); return null; } /// <summary> /// Just call @Html.EmitRequiredStyles() /// at the end of your head tag /// </summary> public static HtmlString EmitRequiredStyles(this IHtmlHelper html) { var ctxt = html.ViewContext.HttpContext; var requiredScripts = ctxt.Items[REQ_STYLE] as List<ResourceToInclude>; if (requiredScripts == null) return null; StringBuilder sb = new StringBuilder(); foreach (var item in requiredScripts.OrderByDescending(i => i.Priority)) { sb.Append(item.ToString()); } return new HtmlString(sb.ToString()); } #endregion Styles #region Models public class InlineResource : Resource { public string Content { get; set; } public override string ToString() { return "<script>"+Content+"</script>"; } } public class ResourceToInclude : Resource { public string Path { get; set; } public string[] Options { get; set; } public override string ToString() { switch(Type) { case ResourceType.CSS: if (Options == null || Options.Length == 0) return String.Format("<link rel=/"stylesheet/" href=/"{0}/" type=/"text/css/" />/n", Path); else return String.Format("<link rel=/"stylesheet/" href=/"{0}/" type=/"text/css/" {1} />/n", Path, String.Join(" ", Options)); default: case ResourceType.Script: if (Options == null || Options.Length == 0) return String.Format("<script src=/"{0}/" type=/"text/javascript/"></script>/n", Path); else return String.Format("<script src=/"{0}/" type=/"text/javascript/" {1}></script>/n", Path, String.Join(" ", Options)); } } } public class Resource { public ResourceType Type { get; set; } public int Priority { get; set; } public bool Bottom { get; set; } } public enum ResourceType { Script, CSS } #endregion Models }

Mis 2 centavos, es una publicación anterior, pero sigue siendo relevante, así que aquí hay una actualización actualizada de la solución del Sr. Bell que funciona con ASP.Net Core.

Permite agregar guiones y estilos al diseño principal desde vistas y subvistas parciales importadas, y la posibilidad de agregar opciones a las importaciones de guiones / estilos (como el aplazamiento asíncrono, etc.):

public static class ScriptsExtensions { const string REQ_SCRIPT = "RequiredScript"; const string REQ_STYLE = "RequiredStyle"; public static string RequireScript(this IHtmlHelper html, string path, int priority = 1, params string[] options) { var ctxt = html.ViewContext.HttpContext; var requiredScripts = ctxt.Items[REQ_SCRIPT] as List<ResourceInclude>; if (requiredScripts == null) ctxt.Items[REQ_SCRIPT] = requiredScripts = new List<ResourceInclude>(); if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority, Options = options }); return null; } public static HtmlString EmitRequiredScripts(this IHtmlHelper html) { var ctxt = html.ViewContext.HttpContext; var requiredScripts = ctxt.Items[REQ_SCRIPT] as List<ResourceInclude>; if (requiredScripts == null) return null; StringBuilder sb = new StringBuilder(); foreach (var item in requiredScripts.OrderByDescending(i => i.Priority)) { if (item.Options == null || item.Options.Length == 0) sb.AppendFormat("<script src=/"{0}/" type=/"text/javascript/"></script>/n", item.Path); else sb.AppendFormat("<script src=/"{0}/" type=/"text/javascript/" {1}></script>/n", item.Path, String.Join(" ", item.Options)); } return new HtmlString(sb.ToString()); } public static string RequireStyle(this IHtmlHelper html, string path, int priority = 1, params string[] options) { var ctxt = html.ViewContext.HttpContext; var requiredScripts = ctxt.Items[REQ_STYLE] as List<ResourceInclude>; if (requiredScripts == null) ctxt.Items[REQ_STYLE] = requiredScripts = new List<ResourceInclude>(); if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority, Options = options }); return null; } public static HtmlString EmitRequiredStyles(this IHtmlHelper html) { var ctxt = html.ViewContext.HttpContext; var requiredScripts = ctxt.Items[REQ_STYLE] as List<ResourceInclude>; if (requiredScripts == null) return null; StringBuilder sb = new StringBuilder(); foreach (var item in requiredScripts.OrderByDescending(i => i.Priority)) { if (item.Options == null || item.Options.Length == 0) sb.AppendFormat("<link rel=/"stylesheet/" href=/"{0}/" type=/"text/css/" />/n", item.Path); else sb.AppendFormat("<link rel=/"stylesheet/" href=/"{0}/" type=/"text/css/" {1} />/n", item.Path, String.Join(" ", item.Options)); } return new HtmlString(sb.ToString()); } public class ResourceInclude { public string Path { get; set; } public int Priority { get; set; } public string[] Options { get; set; } } }