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):
- Make sure you have Visual Studio 2008 SP1 installed.
- On your master page, find the spot where the JQuery library gets included. The line probably looks like this:
- After the preceding line, add this:
Once 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?
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.
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.