jQuery IntelliSense on ASP.NET MVC

You might imagine that getting jQuery IntelliSense working on Visual Studio 2008 and ASP.NET MVC would be trivial. As usual: It is, once you know what to do. Getting there is the trick.


Here are the steps (reasoning comes thereafter):

  1. Make sure you have Visual Studio 2008 SP1 installed.
  2. Install the Visual Studio hotfix (KB958502) for the vsdoc JavaScript help format.
  3. On your master page, find the spot where the JQuery library gets included. The line probably looks like this:
    <script type="text/javascript" src="/scripts/jquery-1.3.2.js"></script>
  4. After the preceding line, add this:
    <% if (false) { %><script type="text/javascript" src="~/scripts/jquery-1.3.2.js"></script><% } %>

imageOnce you’ve done that, JQuery IntelliSense should work just fine on your Master page and all the .aspx views it uses. You can verify this by typing $( onto a script block. If you get the tooltip (see the image on the right), everything is fine. Note that you will get an IntelliSense menu after typing just $ even if the JQuery part of IntelliSense doesn’t work.

One important caveat: Now it works on your master page and full views. It does not work on partial views. Unfortunately, the only way to fix this is by pasting the previous code block (with all the “if (false)” ugliness) into the ascx file.

That hopefully fixed it. Now it’s time to learn the background. There are two key problems with this. First, you have to add the ugly if (false) … reference. Second, you have to add it onto ascx files as well, resulting in lots of copying and pasting, plus extra ugliness. Do note however, that none of it is visible to the end user – this is what you use the if (false) for.

Why do we need that odd double reference?

The Visual Studio JavaScript IntelliSense works by looking for a file with the ending –vsdoc.js. For the ASP.NET MVC standard reference of /scripts/jquery-1.3.2.js, IntelliSense loads up /scripts/jquery-1.3.2-vsdoc.js. Except that it doesn’t, because the meaning of “/” is only relevant when the site is deployed onto a specific host. Therefore, Visual Studio cannot find the file at design time.

Using the tilde (~) syntax allows you to refer to the project’s root – ~/scripts/jquery-1.3.2.js means “the file under the scripts directory in this web project’s root”. This gives Visual Studio a good idea on where to find the file, but of course, no browser can parse this. So, fundamentally, these two syntaxes complement one another. The if (false) part acts as a safeguard, making sure that the jquery file is not included twice on the rendered page. The IntelliSense system bypasses all conditional directives and happily reads in the tilde version even though it is technically conditioned as never executing.

Can you work around it, then? Well, yes and no. You could have just a single reference if you use relative paths like “../../scripts/jquery-1.3.2.js”. It works whenever the file depth and the final URL have the same number of segments. For example, you can use “../..” in /Views/Home/MyPartialView.ascx and it’ll work fine from an IntelliSense perspective. It does, because you’re exactly two levels deep.

However, the rendered page only works when your URI has exactly two segments in it. If the page got rendered as /MyFoobar/Edit/2, everything would be in order. But were the page rendered as /MyFoobar/List/Page/5, the relative reference would resolve as “/MyFoobar/scripts/jquery-1.3.2.js”, resulting in an unloaded JQuery library. Given that ASP.NET Routing is all about separating URIs from the rendering logic, I would strongly advise against coupling of project directories and routes.

How about “<script src="<%=Url.Content("~/scripts/jquery-1.3.2.js") %>" type="text/javascript"></script>” then? That works fine from the published site’s perspective, but Visual Studio cannot run Url.Content at design time, so you will get no IntelliSense.

So no, unfortunately, there doesn’t seem to be a good approach to this – not until Visual Studio starts supporting a more robust notation of JS files being used.

Why do ascx files need the separate instance of the directive?

Compared to the previous explanation, this one is simple. Pages have a reference to a master page, but ascx files do not. They might get rendered into any page, using any master. Therefore, Visual Studio cannot walk up the master tree and find all the script references. That’s the official, understandable explanation.

In practice, the problem might not be that hard to solve. Almost all web projects have one root master page containing the script directives, so at least allowing the developer to mark a master page as “universal” would pretty much solve the issue. The alternative would probably be allowing web.config-level registration of script files (or something similar). But until such a measure is implemented, we will keep pasting.

Resources & References

Be Sociable, Share!

August 6, 2009 · Jouni Heikniemi · 4 Comments
Tags: , ,  · Posted in: .NET, Web

4 Responses

  1. Aki Björklund - August 6, 2009

    I know this is not necessarily a solution to the problem, but you should try keep your scripts external.

    I have personally not found the jQuery intellisense that helpful. The vocabulary of jQuery is so limited. However, if there was a way to visually see how the selector resulted in DOM nodes in real time, that would really speed up the development.

  2. Jouni Heikniemi - August 6, 2009

    I agree re jQuery syntax being reasonably small. On the other hand, you're one of the most competent jQuery developers I know, and thus have naturally very little need for refreshing your memory. Rest of us may need it more though. :-)

    Your idea on the selector visualization has merit, although I understand why people aren't that interested in diving into it; parsing selectors at the source code level with reasonable accuracy isn't exactly trivial, and misleading results can easily occur. Looking forward to somebody's implementation, though!

  3. Heikniemi Hardcoded » Quotation marks either work or are beautiful - September 13, 2009

    [...] recently wrote about getting jQuery IntelliSense working with MVC projects. Well, I went out and copy/pasted the code from the article, not realizing that WordPress had [...]

  4. Suport `Intellisense`pt. JQuery in MVC si VS2010 « Lucian Maran - December 7, 2009

    [...] 1. jQuery IntelliSense on ASP.NET MVC      [...]

Leave a Reply