I recently came across this problem in a project for partial views. For instance if I create a DateTime.cshtml to represent an EditorTemplate for DateTime properties on View Models. I can't just inject the relevant scripts for the jQuery UI Date picker extension using the @section Scripts method like you can do within normal views.
So how can a developer adhere to best practices for stylesheets and script files? By using an extension method.
Let's start with adding a couple of extension methods, Resource and RenderResources as described below.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class ResourceType | |
{ | |
public const string Css = "css"; | |
public const string Js = "js"; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static IHtmlString Resource(this HtmlHelper htmlHelper, Func<object, dynamic> template, string type) | |
{ | |
if (htmlHelper.ViewContext.HttpContext.Items[type] != null) ((List<Func<object, dynamic>>)htmlHelper.ViewContext.HttpContext.Items[type]).Add(template); | |
else htmlHelper.ViewContext.HttpContext.Items[type] = new List<Func<object, dynamic>>() { template }; | |
return new HtmlString(String.Empty); | |
} | |
public static IHtmlString RenderResources(this HtmlHelper htmlHelper, string type) | |
{ | |
if (htmlHelper.ViewContext.HttpContext.Items[type] != null) | |
{ | |
List<Func<object, dynamic>> resources = (List<Func<object, dynamic>>)htmlHelper.ViewContext.HttpContext.Items[type]; | |
foreach (var resource in resources) | |
{ | |
if (resource != null) htmlHelper.ViewContext.Writer.Write(resource(null)); | |
} | |
} | |
return new HtmlString(String.Empty); | |
} |
In the layout:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//at the top of _Layout.cshtml | |
@RenderSection("Styles",false) | |
@Html.RenderResources(ResourceType.Css) | |
//at the bottom of _Layout.cshtml | |
@RenderSection("Scripts",false) | |
@Html.RenderResources(ResourceType.Js) |
In the partial :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//for style sheets | |
@Html.Resource(@<link href="@Url.Content("~/Content/productSummary.css")" rel="stylesheet" />, ResourceType.Css) | |
//for script files | |
@Html.Resource(@<script src="@Url.Content("~/js/productSummary.js")" type="text/javascript" ></script>, ResourceType.Js) |
I haven't tested with Asp .net bundle as yet but with little or no tweaking that should work as well.