1

Question

In ASP.NET MVC (and specifically with Razor), how does one set the value of a variable within a partial (or "sub-template") and access that value within a master (or layout) template?

Goal

I would like to maintain lists of assets (stylesheets and JavaScript files) and be able to add to the lists from within partials. The assets should then be accessible within the master layout to be included in the <head/> (stylesheets) or near the end of the <body/> (JavaScript files) of the page. This provides an elegant means of storing modules in partials that include all necessary assets.

My Attempt

Below is what I have tried for stylesheets. The intended result is that both global.css and view_post.css would be included in the header, but only global.css is showing up. It is my understanding that this occurs because the layout is rendered before the template.

Helpers/AssetHelper.cs

namespace MyApp.Helpers
{
    public static class AssetHelper
    {

        private static SortedSet<string> StyleSheets(this HtmlHelper helper)
        {
            if (helper.ViewBag._styleSheets == null)
                  helper.ViewBag._styleSheets = new SortedSet<string> ();
            return helper.ViewBag._stylesheets as SortedSet<string>;
        }

        public static MvcHtmlString AddStyleSheet(this HtmlHelper helper, string styleSheet) {
            helper.StyleSheets().Add(styleSheet);
            return new MvcHtmlString("");
        }

        public static MvcHtmlString RenderStyles(this HtmlHelper helper)
        {
            StringBuilder output = new StringBuilder();
            string template = "<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}\" />";

            foreach (string styleSheet in helper.StyleSheets())
                output.Append(String.Format(template, styleSheet));

            return new MvcHtmlString(output.ToString());
        }

    }
}

Views/Shared/Layout.cshtml

@using MyApp.Helpers

<html>
  <head>
    ...
    @Html.AddStyleSheet("global.css")
    @Html.RenderStyles()
  </head>
  <body>
    ...
    @RenderBody
    ...
  </body>
</html>

Views/Posts/View.cshtml

@using MyApp.Helpers
@Html.AddStyleSheet("view_post.css")

<h2>...</h2>
<p>...</p>
Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
Andrew Ashbacher
  • 989
  • 10
  • 19
  • Duplicate of [these](http://stackoverflow.com/questions/5312759/trying-to-add-js-and-css-to-layout-file-in-mvc-3-razor-website-from-partial-view?rq=1) [three](http://stackoverflow.com/questions/5981490/how-to-render-javascript-into-masterlayout-section-from-partial-view/6671766#6671766) [questions](http://stackoverflow.com/questions/5110028/add-css-or-js-files-to-layout-head-from-views-or-partial-views/7343340#7343340). I just needed the **Related** sidebar after posting my question. :) – Andrew Ashbacher May 07 '13 at 01:02
  • None of those answer actually answer the question you asked. They are simply ways to set the css or scripts via children, and have nothing whatsoever to do with setting a variable in a partial and using it in a parent (the question you asked about). – Erik Funkenbusch May 07 '13 at 01:14

1 Answers1

4

You can't. Layout templates are rendered before your partials. Any variable you set in a partial will be set too late for the layout to know it's there.

This seems like an over complex solution. Why don't you just use the WebOptimization tools that MVC provides?

Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
  • 5
    Saying you can't do something does not answer how to do it. And just because you don't know how doesn't mean it is not possible. – Andrew Ashbacher May 07 '13 at 01:05
  • 2
    @AndrewAshbacher - It's absolutely not possible to set a c# variable in a partial and use it in a layout. Downvoting me for answering the question you asked (rather than the question you seem to have meant) is very poor netiquette. Yes, you can set scripts in the layout in a number of ways, but not via the question you specifically asked. – Erik Funkenbusch May 07 '13 at 01:13
  • Fair enough. I'll be sure to phrase the actual question appropriately in the future. That said, this is not an overly complex solution as it simplifies a great deal of code elsewhere. We are using [something similar](https://github.com/ServiceStack/Bundler) to WebOptimization. But, we would like to also modularize and improve reusability of our code. – Andrew Ashbacher May 07 '13 at 16:01