I followed a now deleted blog (see all my code below for what I did) to create a basic RequireJS structure in MVC. While in IIS Express everything works as expected. When in IIS the core module is not found. The only difference between the two (IIS and IIS Express) is that the Map Paths shows wwwroot for IIS and the actual file path where I am developing for IIS Express. Here is the code I am referring to that builds the require script.
if (File.Exists(helper.ViewContext.HttpContext.Server.MapPath(Path.Combine(jsLocation, module + ".js"))))
{
require.AppendLine("require( [ \"" + jsLocation + core + "\" ], function() {");
require.AppendLine(" require( [ \"" + module + "\"] );");
require.AppendLine("});");
}
SOLUTION
Replace the above AppendLines that have dependency names with the following structure. The VirtualPathUtility is what was needed.
require.AppendLine("require( [ \"" + VirtualPathUtility.ToAbsolute("~/" + jsLocation + core) + "\" ], function() {");
END SOLUTION
Here is my file structure (root project MVCTesting)
Scripts
require.js
-AMD
core.js
-Views
-JQuery
AMDRequire.js
If my layout.cshtml contains the require in the following format (Note: for some reason it is allowing me to put the .js in the module name, not sure on that one).
<script type="text/javascript">
require( [ "/Scripts/AMD/core.js" ], function() {});
</script>
What should the format of the dependency name ("/Scripts/AMD/core.js") be to correctly load while in MVC and using IIS? My project name is MVCTesting, so I have tried "/MVCTesting/Scripts/AMD/core.js" and various combinations with the forward slash manually without any luck.
UPDATE
Code in AMDRequire.js
alert("HELLO AMD WORLD!");
IIS Express
Full URL: http://localhost:55916/jquery/amdrequire
Project Url (Project Properties): http://localhost:55916/
Results: Displays alert message HELLO AMD WORLD!
IIS
Full URL: http://localhost/MVCTesting/jquery/amdrequire
Project URL (Project Properties): http://localhost/MVCTesting
Results: No display message, I am assuming because the js file was not file
Final Code (Note, I recommend using AngularJS over this)
#region DOJO AMD Loader
/// <summary>
/// Create the javascript required to use DOJO while following AMD specifications
///
/// Just place @Html.DOJOAMDLoader() in your Layout or other cshtml that you want to use
/// this and it will populate the dojoConfig, the script include for dojo, and the current
/// page's AMD JavaScript file.
/// </summary>
/// <param name="helper"></param>
/// <param name="bsndm"></param>
/// <param name="btsRoot"></param>
/// <returns></returns>
public static MvcHtmlString DOJOAMDLoader(this HtmlHelper helper)
{
var action = helper.ViewContext.RouteData.Values["action"].ToString().ToLower();
var controller = helper.ViewContext.RouteData.Values["controller"].ToString().ToLower();
return helper.CreateDOJORequire(controller, action,
BuildInitJsLogging(ConfigurationManager.AppSettings["JavascriptLoggingLevel"],
ConfigurationManager.AppSettings["JavascriptLoggingAllowDisplayOverride"]));
}
/// <summary>
/// Kick off the custom js logging, display is handled inside the logging JS
/// </summary>
/// <param name="logLevel">The state of the js log (expects Off, On, File)</param>
/// <param name="displayOverride">For failure to log to files, display to screen override</param>
/// <returns></returns>
private static string BuildInitJsLogging(string logLevel, string displayOverride)
{
//This is not used for non system pages or test pages
if (logLevel == null)
{
return null;
}
var updateVariable = new StringBuilder();
updateVariable.AppendLine("require(['logging', 'dojo/domReady!'], function (logging) {");
updateVariable.AppendFormat("logging.initJsLogging('{0}','{1}');", logLevel, displayOverride);
updateVariable.AppendLine("});");
return updateVariable.ToString();
}
/// <summary>
/// This builds the script that will be placed on the page for DOJOAMDLoader
///
/// Included scripts will be the dojoConfig, the script include for dojo, and the currnet
/// page's AMD JavaScript file.
/// </summary>
/// <param name="helper"></param>
/// <param name="controller"></param>
/// <param name="action"></param>
/// <returns></returns>
private static MvcHtmlString CreateDOJORequire(this HtmlHelper helper, string controller
, string action, string javascriptLogging)
{
//Don't build require string if there is not an amd script
if (!File.Exists(helper.ViewContext.HttpContext.Server.MapPath(
GetAbsolutePath(Path.Combine("Scripts", "AMD", "Views", controller, action + ".js")))))
{
return null;
}
//TODO:HP:At the end of the project before going live, merge these
//into as few AppendLine statements as possible.
var require = new StringBuilder();
require.AppendLine("<script>");
require.AppendLine("dojoConfig = {");
require.AppendLine(" async: true,");
require.AppendLine(" packages: [");
require.AppendLine(BuildPackageScriptText("jquery", "Scripts/ThirdParty/jQuery", "jquery-1.9.1", true));
require.AppendLine(BuildPackageScriptText("jquery-ui", "Scripts/ThirdParty/jQuery", "jquery-ui-1.10.2"));
require.Append(BuildPackageScriptText("jquery-loadmask", "Scripts/ThirdParty/jQuery", "jquery.loadmask"));
require.AppendLine(BuildPackageScriptText("jsfunctions", "Scripts/Common", "jsfunctions"));
require.AppendLine(BuildPackageScriptText("logging", "Scripts/TJPackages", "JsLogging"));
require.AppendLine(BuildPackageScriptText(action, string.Format("Scripts/AMD/Views/{0}", controller), action));
require.AppendLine(" ]");
require.AppendLine("};");
require.AppendLine("</script>");
require.AppendLine("<script src='" + GetAbsolutePath("Scripts/ThirdParty/ESRI/init.js") + "'></script>");
require.AppendLine("<script>");
require.AppendLine(javascriptLogging);
require.AppendFormat("require(['{0}', 'dojo/domReady!'],function({0})", action);
require.AppendLine("{");
//require.AppendLine("debugger;");
require.AppendFormat(" {0}.init();", action);
require.AppendLine("});");
require.AppendLine("</script>");
return new MvcHtmlString(require.ToString());
}
/// <summary>
/// Common format for packages in the dojoConfig
/// </summary>
/// <param name="name"></param>
/// <param name="location"></param>
/// <param name="main"></param>
/// <param name="isFirst">Set to true for the first package and the comma will NOT be appended</param>
/// <param name="isCDN">Set to true if using a CDN location for your javascript</param>
/// <returns></returns>
private static string BuildPackageScriptText(string name, string location, string main, bool isFirst = false, bool isCDN = false)
{
var sb = new StringBuilder();
if (!isFirst)
{
sb.Append(",");
}
sb.Append("{");
sb.AppendFormat("name: '{0}', location: '{1}', main: '{2}'", name, isCDN ? location : GetAbsolutePath(location), main);
sb.Append("}");
return sb.ToString();
}
#endregion
/// <summary>
/// Convert the path to work in IIS for MVC
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
private static string GetAbsolutePath(string path)
{
return VirtualPathUtility.ToAbsolute("~/" + path);
}