8

I am starting with first MVC application. Here i have the basic confusion. Actually the default _Layout.cshtml file created like below

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")

</head>
<body>
    <script>

    </script>
    @RenderBody()

    @Scripts.Render("~/bundles/jquery")
    @RenderSection("scripts", required: false)
</body>
</html>

I used basic template so not have any template. But check the '@Scripts.Render("~/bundles/jquery")' line. Its after the @RenderBody(). So it actually it adds after the body section.

I think this is actually the best practice. But if i add $.(document).ready it shows the following error

Microsoft JScript runtime error: '$' is undefined

Based on the error, it because of script tag. I just moved the '@Scripts.Render("~/bundles/jquery")' line before @Render body and the final page like

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    @Scripts.Render("~/bundles/jquery")

</head>
<body>
    <script>

    </script>
    @RenderBody()      
    @RenderSection("scripts", required: false)
</body>
</html>

The applicationw works fine with my jquery.

So why this is happened? So always the script adding tag need before @RenderBody ? Then why default template showing in wrong location?

tereško
  • 58,060
  • 25
  • 98
  • 150
Akhil
  • 1,918
  • 5
  • 30
  • 74
  • thanks satpal for edit. I am editing actually. – Akhil Mar 24 '14 at 08:05
  • jQuery was not loaded thus you were getting error `'$' is undefined`. As you move `@Scripts.Render("~/bundles/jquery")` in the head section first jquery got loaded then you code executed – Satpal Mar 24 '14 at 08:08
  • There is a reason why the default template is constructed like this. Moving the jQuery bundle to head will solve your problem, but introduce other problems on client side (think about UX). You should take the advice from @Ufuk Hacıoğulları – ljubomir Mar 24 '14 at 08:29

3 Answers3

17

This probably happens because you are adding the scripts before the jQuery reference in the page. You need to write scripts inside scripts section in your views:

@section scripts {
    //stuff
}

This will make sure it will be rendered after the jQuery reference(RenderSection call).

Ufuk Hacıoğulları
  • 37,978
  • 12
  • 114
  • 156
  • Solution to **add custom script optionally** with use of if script is defined, check [this](http://stackoverflow.com/a/7357102/2218697) – Shaiju T Sep 10 '16 at 12:09
1

@Scripts.Render does not render scripts in the scripts section. It renders the appropriate script tag where the call is made.

To achieve what you are after, this is pretty much the layout I use:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")    
</head>
<body>
    @RenderBody()
    @Scripts.Render("~/bundles/jquery")
    <script>
        $(function() {
        });
    </script>
    @RenderSection("scripts", required: false)
</body>
</html>

Likewise, @RenderSection is useful in views that utilize this layout, and in this case would be used like:

@section scripts {
    <script>
        $(function() {
        });
    </script>
}

It is typically advised to not use inline scripts in the body, so rendering jQuery at the bottom in this order will work fine.

Steve Andrews
  • 561
  • 3
  • 14
0

jQuery should be in the head and any custom scripts you write should be at the bottom after the body.

This is because if you use any jQuery in your body and it is not wrapped in a document.ready it will try to execute before jQuery has been loaded and you will receive a $ is undefined error

logikal
  • 1,123
  • 13
  • 26