Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC executing view code before layout code and ruining my script order

I'm trying to move all of my javascript includes to the bottom of the page. I'm using MVC with Razor. I've written a helper method to register scripts. It keeps the scripts in the order they're registered and it excludes dupes.

@{ Html.RegisterScript("/scripts/someFile.js"); }

And then right before the closing body tag I do something like this:

    @Html.RenderScripts()
</body>

This all works fine if the scripts are registered all on one page. If I register some scripts in my layout, and some scripts in my inner view, things go awry. Basically, the inner view is executing before the layout. So event though the scripts in the inner view depend on the scripts in the outer view, they're being registered prior.

So if I have _Master.cshstml and it has

@{
   Html.RegisterScript("script1.js");
   Html.RegisterScript("script2.js");
}

And then I have InnerView.cshtml with _Master.cshtml as its layout and in the view I have

@{
   Html.RegisterScript("script3.js");
}

The scripts get rendered out in this order: script3, script1, script 2.

Is there any way I can force the layout to execute before the inner view? I've tried moving things all over the place and everything the inner view always seems to execute first. Perhaps this is expected? If so, what is the best way for me to accomplish what I'm trying to do?

like image 438
Eric Avatar asked Nov 04 '11 16:11

Eric


People also ask

How do I use RenderSection in partial view?

You can render the partial view in the parent view using the HTML helper methods: @html. Partial() , @html. RenderPartial() , and @html. RenderAction() .

Which of the following can be used to instruct the view engine to Ignore the body or sections?

To instruct the view engine to ignore the body or sections, call the IgnoreBody and IgnoreSection methods. The body and every section in a Razor page must be either rendered or ignored.

What is @section scripts in MVC?

@section allows you to include those files only for certain views. It is needed since, a view cannot easily change the contents of the _Layout. cshtml otherwise. You can also position the @section at the bottom of the layout, for JavaScript files for example, or at the top of the layout, for CSS files.


1 Answers

No, that's the order that they execute, from inner-most to outer-most. I would recommend using some kind of LIFO (last in first out) collection like Stack<T> to hold the scripts in and then pop them off the stack to render them out; this way, the scripts added last i.e. the ones in the layout, will be the ones that are rendered first.

EDIT

I wrote a nuget package that handles rendering scripts from Partial views and Templates that solves this problem.

like image 173
Russ Cam Avatar answered Oct 11 '22 13:10

Russ Cam