Как мне отформатировать имена зависимостей для RequireJS в MVC при использовании IIS?

Я следовал за теперь удаленным блогом (см. Весь мой код ниже для того, что я сделал), чтобы создать базовую структуру RequireJS в MVC. Пока в IIS Express все работает как положено. Когда в IIS основной модуль не найден. Единственное различие между ними (IIS и IIS Express) заключается в том, что в путях к карте отображается wwwroot для IIS и фактический путь к файлу, который я разрабатываю для IIS Express. Вот код, на который я ссылаюсь, который создает скрипт require.

        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("});");
        }

РЕШЕНИЕ

Замените вышеупомянутые AppendLines, которые имеют имена зависимостей, следующей структурой. VirtualPathUtility - это то, что было нужно.

require.AppendLine("require( [ \"" + VirtualPathUtility.ToAbsolute("~/" + jsLocation + core) + "\" ], function() {");

КОНЕЧНОЕ РЕШЕНИЕ

Вот моя файловая структура (корневой проект MVCTesting)

Scripts
   require.js
   -AMD
      core.js
      -Views
         -JQuery
          AMDRequire.js

Если мой файл layout.cshtml содержит требуемый файл в следующем формате (примечание: по какой-то причине он позволяет мне добавлять.js в имя модуля, но я не уверен в этом).

    <script type="text/javascript">
        require( [ "/Scripts/AMD/core.js" ], function() {});
    </script>

Каким должен быть формат имени зависимости ("/Scripts/AMD/core.js") для правильной загрузки в MVC и с использованием IIS? Мой проект называется MVCTesting, поэтому я попробовал "/MVCTesting/Scripts/AMD/core.js" и различные комбинации с косой чертой вручную без какой-либо удачи.

ОБНОВИТЬ

Код в 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

Окончательный код (обратите внимание, я рекомендую использовать AngularJS для этого)

    #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);
    }

1 ответ

Решение

Я думаю, что вам нужно переписать код C#, чтобы использовать Url.Content()функция:

Преобразует виртуальный (относительный) путь в абсолютный путь приложения.

Но чтобы убедиться, что вы должны проверить, выполняет ли он работу для приложений в подпапке (т.е. MVCTesting). В вашем коде (например, в файле _layout) просто напишите:

@Url.Content("/Scripts/AMD/core.js")

На localhost вывод должен быть что-то вроде /Scripts/AMD/core.js, но в IIS это должно быть /MVCTesting/Scripts/AMD/core.js, Дайте мне знать, если это так.

Другие вопросы по тегам