Jon Davis
Jon Davis

Reputation: 6763

What is the best way to include script references in ASP.NET MVC views?

As you know, ASP.NET MVC stores view markup in a Views directory, which is hierarchically incompatible with the URL routes that are used in an ASP.NET MVC web application. On the opposite end, in ASP.NET Web Forms (and in ASP.NET MVC, too), URLs can and usually do have nested "directories", or rather path separators, and this combined with the fact that web applications are often not hosted in the root path of a URL but rather in a sub-directory i.e. "/stuff/here/MyActualApp", it is necessary to use a script path relative to the root of the application rather than relative to the root of a URL. Meanwhile, however, Visual Studio script intellisense dictates that URLs map relatively to the file being edited.

Further, I've run into a lot of problems with using runat="server" to virtualize the root path to support "~/", such as the head tag needing to also be runat="server", and this introduces all kinds of other constraints.

Finally, one more thing: if the minified flavor of a script like jQuery is referenced in addition to the intellisense-ready flavor, Visual Studio will balk on it. So you almost have to use escaped code to keep VS from balking.

So I've been using this syntax, or variations of it, in Visual Studio 2010 since VS 2005 for including script in my ASP.NET view markup to deal with the discrepancies nested folders for ASP.NET MVC view files (which do not line up with actual URLs) as well as the need to use the vsdoc flavor of jQuery instead of the minified version so that I get intellisense working.

<%if (false) { %>
<script src="../../Scripts/jquery-1.4.1-vsdoc.js" type="text/javascript"></script>
<% } %>
<%= "<script type=\"text/javascript\"" src=\"" 
  + ResolveUrl("~/Scripts/jquery-1.4.1.min.js") + "\"></script>"%>

Aside from using a CDN URL, is there a better way than this? It's ugly. I wish Microsoft could have addressed this by now without resorting to ScriptManager tags (which require server-side forms as well as make the markup even more verbose).

Note: My issue is not with the Intellisense support so much as the last line in the code above, having to emit a line rather than just using real markup. However, I also want intellisense support readiness, too.

Upvotes: 2

Views: 2607

Answers (4)

Jon Davis
Jon Davis

Reputation: 6763

In ASP.NET MVC 4, Razor has become smart enough to support "~/" detection. Hopefully the VS11 IntelliSense tooling will keep up with this.

<script src="~/Scripts/Controls.js"></script>

New in ASP.NET MVC4: Razor changes (Alexander Beletsky)

Meanwhile, the Visual Studio tooling and the jQuery source (since jQuery was used for reference in the question) have both been heavily modified since the question was originally asked. RickAndMSFT's answer did not apply at that time. At the current time, his answer is correct; however, since this is a moving target it appears that by the end of this year one would just reference the script directly and Razor and revised VS tooling will take care of everything.

Upvotes: -1

RickAndMSFT
RickAndMSFT

Reputation: 22800

As you know, ASP.NET MVC stores view markup in a Views directory, which is hierarchically incompatible with the URL routes that are used in an ASP.NET MVC web application

That is incorrect. In what way do you think the default view directory is incompatible with routing?

On the opposite end, in ASP.NET Web Forms (and in ASP.NET MVC, too), URLs can and usually do have nested "directories", or rather path separators, and this combined with the fact that web applications are often not hosted in the root path of a URL but rather in a sub-directory i.e. "/stuff/here/MyActualApp", it is necessary to use a script path relative to the root of the application rather than relative to the root of a URL

it is necessary to use a script path relative to the root of the application rather than relative to the root of a URL

WHat does root or the Url mean? MVC doesn't use nested directorys by default (unless you set RouteExistingFiles to true) What does it mean for a URL to have nested directories? MVC routing uses segments not path seperators.

applications are often not hosted in the root path of a URL but rather in a sub-directory More correctly, apps are hosted in a vdir which is not at the root level. With MVC 3 and lower you need to reference static resources (css, javaScript) using the @Url.Content helper.

With MVC 4/Beta + Razor and higher, you no longer need to use the @Url.Content helper.

Further, I've run into a lot of problems with using runat="server" to virtualize the root path to support "~/", such as the head tag needing to also be runat="server", and this introduces all kinds of other constraints

You should never use runat="server" with a MVC application to virtualize the root path.

the need to use the vsdoc flavor of jQuery instead of the minified version so that I get intellisense working. That again is incorrect. You should NEVER reference the vdoc versions directly. Visual Studio/VWD detects when a .vdoc version of a script file is present and enable intellesence.

Your helper approach is probably the best route. You could modify my helper approach http://blogs.msdn.com/b/rickandy/archive/2011/05/21/using-cdns-to-improve-web-site-performance.aspx

Typically folks comment out the .min references for development the switch comments for production to use the minified version. We are actually working on an approach to toggle development/production using minificatin/bundling. see RequestReduce. and http://weblogs.asp.net/scottgu/archive/2011/11/27/new-bundling-and-minification-support-asp-net-4-5-series.aspx

Upvotes: 2

quentin-starin
quentin-starin

Reputation: 26638

We use SquishIt. It combines and minifies the files, too, and supports css (and even dotLess).

<head>
  <%= Bundle.Css()
    .Add("~/media/css/style.less")
    .Add("~/media/css/print.css")
    .Add("~/media/css/media.css")
    .Render("~/media/css/styles_#.css") %>
  <%= Bundle.JavaScript()
    .Add("~/media/js/jquery-1.4.3.js")
    .Add("~/media/js/jquery.equalHeights.js")
    .Add("~/media/js/jquery.cycle.lite.1.0.js")
    .Add("~/media/js/swfobject-2.2.js")
    .Add("~/media/js/site.js")
    .Render("~/media/js/js_#.js") %>
</head>

T4MVC can also provide a way to reference the URL's:

<script src="<%= Links.Scripts.Map_js %>" type="text/javascript"></script>

Upvotes: 6

kobe
kobe

Reputation: 15835

you can give something like this during development , and so that it will show you the intellisens

<reference path="http://code.jquery.com/jquery-1.4.1.js"/>

Upvotes: 0

Related Questions