4

I have asp.net mvc application, that uses razor view engine.

I want to send head to browser, before body renders, to start parallel loading css, js and images, linked in css. (You can see, how this technique works on SO in chrome developer tools - network for example) I found question about it in asp.net web forms: Send head before body to load CSS and JS asap I tried to use this solution, but it don't work.

For razor engine next sequense of steps is actual:

  1. action returns view result
  2. _ViewStart.cshtml executes (set ViewBag.Layout)
  3. view executes from first line to last (with code inclusions and sections)
  4. view engine checks ViewBag.Layout and if it found - executes Layout (with renderind body and sections)

I think that good solution is to divide step 3 into 3 parts:

  1. generating content for Head and Css section
  2. send to browser
  3. generating other part of view

Other solution is to static include all.css and basic .js files in (without sections content, generated from view), send head, and then generate view (with generation FooterScript section).

In both ways I need to start execution from Layout page, not from view. For first: Layout (head) - view (sections) - layout (flush) - view (other) - layout (body). For second: Layout (head + flush) - view (all) + Layout (body).

My _Layout.cshtml file:

<html @Html.Raw(ViewBag.xmlns)>
    <head>
        <title>@ViewBag.Title</title>
        @Html.Partial("_MetaTags")    
        <link href="@Url.ThemeCss("jquery-ui-1.8.18.custom.css")" rel="stylesheet" type="text/css" />
        <link href="@Url.Css("masterPage.css")" rel="stylesheet" type="text/css" />          
        <link rel="shortcut icon" href="/favicon.ico"/>

        @RenderSection("Css", required: false)
        <script src="@Url.CommonScript("jquery.common.min.js")" type="text/javascript"></script>
        <script src="@Url.Script("Master.js")" type="text/javascript"></script>        
        @RenderSection("Head", required: false)    
    </head>

    <body>
        <div id="pageWhithoutFooter">    
            <div id="main">
                @RenderBody()
            </div>
        </div>
        @RenderSection("FooterScript", required: false)
    </body>
</html>

Howto?

Community
  • 1
  • 1
David Levin
  • 6,573
  • 5
  • 48
  • 80

1 Answers1

3

Try putting your head section into a Partial view then call this in your controller:

PartialView("_PageHeader").ExecuteResult(ControllerContext);
Response.Flush();

// Generate model

return View(model);

Not tested this but I can't see why it wouldn't work.

greg84
  • 7,541
  • 3
  • 36
  • 45
  • How should partial look like: ...static includes... and layout should look like: @RenderBody() ? – David Levin Apr 17 '12 at 10:38
  • That sounds about right. You could wrap the logic in my answer in an attribute or something for each action you want to apply it to. – greg84 Apr 17 '12 at 10:41
  • Would it be compilable without closing/opening tags? I use pre-compile option for release build mode. – David Levin Apr 17 '12 at 10:52
  • Bad that you not tested it. Because I can't see why @{Response.Flush(); } don't work when placed between and

    but it don't.

    – David Levin Apr 17 '12 at 10:56
  • 1
    That doesn't work because at the time it's called nothing has been written to the response stream - that's what the ExecuteResult method does in my answer above. – greg84 Apr 17 '12 at 11:18