Wednesday, July 1, 2015

How to fix "$ is not a function", "$ or jQuery are not defined" errors

In this post, I'll be explaining time tested remedies for the below erros commonly seen in ASP.NET MVC applications -

SyntaxError: missing } in compound statement

ReferenceError: jQuery is not defined

ReferenceError: $ is not defined

TypeError: $ is not a function

You're likely to see these errors when deploying a new application or if you have made modifications to the BundleConfig.cs, _Layout.cshtml, master pages or other such files. I realize that the files that I listed are ASP.NET MVC specific, but the resolutions that I will be listing below apply to most technologies out there. BundleConfig.cs and _Layout.cshtml just refer to the places in ASP.NET MVC where we usually tell the ASP.NET MVC application where the scripts and styles are reside.

So, the error message "jQuery is not defined" clearly tells us that the jQuery script reference is missing. But when you you look in your scripts folder, it's there. The other errors don't even explain what could be wrong, but fear not, try out the below decetively simple resolutions and your errors should go away in a jiffy -

  1. Check to ensure that the jquery file with the proper version is indeed present in your Scripts (or wherever you store the script files) folder - The jquery version part seems to cause these issues quite a bit, so ensure that the version referenced in your view/webpage is exactly the same as the version in the name of the file. In ASP.NET MVC world, you have the option to replace the version number with {version}, that is very helpful in avoiding this problem. So, your BundleConfig.cs will look like
    bundles.Add(new ScriptBundle("~/bundles/jquery").Include("~/Scripts/jquery-{version}.js"));
  2. Ensure that the script reference to your jquery file is indeed there in the rendered HTML page - This goes without saying but in an ASP.NET MVC application, sometimes the scripts will be bundled based on the setting of BundleTable.EnableOptimizations, which makes it almost impossible to see which scripts are actually referenced. Try setting BundleTable.EnableOptimizations to false to be able to see the script tags in the rendered page. I'll go further into the details of how to do it and where in the next item.
  3. Check whether Bundle optimizations are on or off - Another commonly overlooked issue results from the default settings of the optimizations. Basically, ASP.NET MVC allows us to pick the minified versions and regular versions of script files based on this configuration setting. If you're not familiar with it, look for BundleTable.EnableOptimizations in the RegisterBundles method of your BundleConfig.cs file. If you see something like
    BundleTable.EnableOptimizations = true;
    then the application will be looking for the minified version of the scripts regardless of the name of the file in your BundleCollection. For example, if your jquery file is called, jquery-3.0.1.js and your BundleCollection line says ScriptBundle("~/bundles/jquery").Include("~/Scripts/jquery-{version}.js")); and BundleTable.EnableOptimizations is set to true, then the app will be looking for jquery-3.0.1.min.js and not the jquery-3.0.1.js file. The solution here is to just uploading the minified jquery-3.0.1.min.js file. If you don't have the minified file, then you could set the BundleTable.EnableOptimizations to false and that would remedy it. A side benefit of setting the BundleTable.EnableOptimizations to false for testing is that then you'd be able to see the script tags on the rendered HTML page for each of your scripts, as I mentioned in a previous point. On a side note, you'd also want to check whether your Web.Config is set to debug or release mode.
  4. Ensure that the jquery script reference occurs before any other script references in the webapge/view - This is another common problem when some other scripts that need jquery appear in your script reference section before the jquery file reference. These scripts look for jquery but the jquery file is not loaded because it's referenced further down the line. Just put the jquery reference on the top of your scripts section and you should be good.
  5. Ensure that the jquery reference occurs before other references inside the BundleConfig.cs - The scripts added to the ASP.NET MVC ScriptsBundle render in the same order in which they appear in the BundleConfig.cs file. The remedy is simple, just put the ScriptBundle("~/bundles/jquery").Include("~/Scripts/jquery-{version}.js")); line at the top of your RegisterBundles method.
  6. Check the file sizes of the jquery file on your deployment server - This one almost sounds silly but I've seen cases when the file is not properly uploaded during deployment because of FTP errors etc. The way normal FTP works, if something breaks down during the STOR request in the middle of a big upload, at times the files being uploaded will stay on the server even though they were not fully uploaded. In other words, your file gets partially uploaded (or just an empty file is uploaded) when the upload request fails and now a cursory look will reveal that the file is there...but well, not really. If you don't have access to the production server, then it'd help to look at the logs for any errors during uploads (yes, many of the FTP clients are set to keep going in case of errors).
  7. Check the chaching mechanism of your app - Sometimes the app will cache bad files or sections of pages etc and no matter how many times you refresh, the problem won't go away. One less than ideal solution that I use is deleting the BundleCollection contents completely. You can do this by adding the following lines to the top of your RegisterBundles method in the BundleConfig.cs file (you wouldn't want to do it in the production code though) -
    bundles.Clear(); bundles.ResetAll();

So, basically to summarize, we want to ensure that the name of the your jquery file matches exactly with the file name that shows up in the script tag in your view, masterpage, _layout.cshtml etc...and the size of the file matches and that the jquery reference script tag appears before all other scripts that you might be including. That's about it. In ASP.NET MVC world, there could be further complications because of the BundleConfig or WebConfig settings, but they're also easy to get around by a few small changes.

No comments:

Post a Comment