【问题标题】:Simply cannot make SignalR (asp.net mvc4) and require.js work together根本无法让 SignalR (asp.net mvc4) 和 require.js 一起工作
【发布时间】:2013-08-02 16:48:35
【问题描述】:

我在网上看到过类似的帖子,但没有人建议对我有用。在这一点上,我真的面临着一个或另一个倾销的选择。

此“SignalR 和 MVC 4 入门教程”:

http://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr-and-mvc-4

说您需要包含两个脚本才能使 signalR 工作:

    <!--Reference the SignalR library. -->
    <script src="~/Scripts/jquery.signalR-1.0.1.js"></script>
    <!--Reference the autogenerated SignalR hub script. -->
    <script src="~/signalr/hubs"></script>

我不知道如何在 require.js 中制作第二个自动生成的 SignalR 集线器脚本。除非我遗漏了一些东西,否则似乎没有一个可行的 require.js 语法来包含自动生成的脚本。如果没有它,您会在 jquery.signalR-1.1.2.js 的第 159 行收到此错误:

“JavaScript 运行时错误:SignalR:加载集线器时出错。确保您的集线器引用正确,例如”

jquery.signalR 中的代码正在执行此操作:

    signalR.hub = {
            start: function () {
                // This will get replaced with the real hub connection start method when hubs is referenced correctly
                throw new Error("SignalR: Error loading hubs. Ensure your hubs reference is correct, e.g. <script src='/signalr/hubs'></script>.");
        }
    };

有没有人真的通过 require.js 实现了这个自动生成的脚本?

对此进行了更多研究。让我补充一些细节:

我正在使用这种方法 - 构建可扩展的客户端应用程序:(http://johndavidmathis.wordpress.com/2013/04/23/structuring-scalable-client-side-applications/) 以构建更具可扩展性的结构。该系列的第二部分“允许模块使用多个文件和逻辑文件夹结构”http://johndavidmathis.wordpress.com/2013/04/23/structuring-scalable-client-side-applications/ 让我将我的实际信号器代码拆分为一个单独的 Marionette 聊天模块(与我的主 app.js 文件分开)以获得更好的文件结构体。我真的很喜欢这种方法。我的项目的其余部分现在都是这样设置的,在查找代码方面确实显示出了好处。我认为额外的拆分是我卡住的地方。似乎无法将第二个依赖项(自动生成的脚本)放入单独的聊天模块文件中。我仍在研究这个,但在这一点上对我来说是这样的。 require.js 将依赖项添加到我的 Marionette 应用程序中:

    require(["marionette","handlebars", "signalr", "signalr.hubs"], function (Marionette) {
        window.App = new Marionette.Application();

        App.addRegions({
            headerRegion: "#header",
            contentRegion: "#content",
            footerRegion: "#footer",
        });            

        require(["modules/main/loader", "modules/chat/loader"], function () {
            App.start();
        });
    })

如果我想让聊天依赖项进一步进入应用程序,进入另一个文件中的聊天模块?

类似的东西?

    define(dependencies,
        function () {
            App.module("ChatModule", function (ChatModule, App, Backbone, Marionette, $, _, "signalr.hubs", "signalr.hubs") {

            // SignalR Proxy created on the fly
                var chat = $.connection.chatHub;

                // Start the connection
                $.connection.hub.start();

    //more chat code...

更新:

下面的答案在我的开发环境中确实有效。但是当我将代码发布到真正的生产服务器时它不起作用。

当代码发布到真正的生产服务器(Windows Server Enterprise 2008 R2 上的 IIS 6.1)时,浏览器控制台再次显示“404”作为自动生成的引用。

具体来说,控制台显示“?”正在被添加到“.js”之前的引用路径中,像这样...

http://mydomain.com/myapp/Scripts/application/signalr/hubs?.js...

尝试使用“?” out 但随后它会从路径中删除我的应用程序名称,就像这样......

http://mydomain.com/signalr/hubs.js.

我认为第一个没有“?”,比如...

http://mydomain.com/myapp/Scripts/application/signalr/hubs.js

我只是不知道如何做到这一点。

最终更新:

生产服务器的最后一个难题是站点的虚拟目录。这是对我有用的最终代码。感谢 Raciel R 的帮助:

    requirejs.config({        
        paths: {
            //core
            "jquery": "jquery-1.9.1",

            "signalr": "jquery.signalR-1.1.2",
            "signalr.hubs": "/productionservervirtualdirectory/signalr/hubs?"
        },
        shim: {
            "jquery": {exports: "$"},            
            "signalr": { deps: ["jquery"] },
            "signalr.hubs": { deps: ["signalr"] }
        });
    //Then all you have to do is to make signalr.hubs required in your modules. Ie:

    require(["signalr.hubs"], function(){
         //your code here
    });

【问题讨论】:

  • 你在服务器上调用过 MapHubs 吗?请参阅问题:stackoverflow.com/questions/16235175/…,这与您遇到的情况相反,但应该回答您的问题。
  • 是的。做过某事。没有骰子。问题似乎非常具体地是缺少进行第二次引用的 require.js 语法 - 自动生成的 SignalR 集线器脚本。我看到人们对语法进行了各种尝试。我已经尝试了所有这些,但没有一个对我有用。下面的一个对我也不起作用。

标签: asp.net-mvc-4 requirejs signalr marionette


【解决方案1】:
requirejs.config({        
    paths: {
        //core
        "jquery": "jquery-1.9.1",

        "signalr": "jquery.signalR-1.1.2",
        "signalr.hubs": "/signalr/hubs?"
    },
    shim: {
        "jquery": {exports: "$"},            
        "signalr": { deps: ["jquery"] },
        "signalr.hubs": { deps: ["signalr"] }
    });

那么您所要做的就是使您的模块中需要 signalr.hubs。即:

require(["signalr.hubs"], function(){
     //your code here
});

【讨论】:

  • 谢谢。没有骰子。我认为其中大部分可能是有效的。我还有一个皱纹,不过我已经添加到我原来的帖子中了。我正在使用这种方法 - 构建可扩展的客户端应用程序:(johndavidmathis.wordpress.com/2013/04/23/…)。该系列的第二部分让我将我的实际信号器代码拆分为一个单独的 Marionette 聊天模块。我认为这就是它失败的地方。似乎无法将第二个依赖项(自动生成的脚本)放入单独的聊天模块中。查看我的编辑。
  • 无论您使用的客户端代码组织和技术如何,它都应该可以工作。这里棘手的部分(我在集成信号器时遇到了同样的问题)是自动生成的文件,可以通过添加?最后防止 require.js 弄乱它。我也尝试了 noext 插件,但我没有运气。我建议的方法是由另一位 SO 研究员向我建议的。 Require.js 垫片和路径对于描述不是以 require.js 方式编写的模块之间的依赖关系非常强大,对于您自己的模块,您只需正确定义它们就可以了。
  • 我会尝试从一个简单的场景开始,然后慢慢地引入更多的复杂性,这样你就可以知道哪里出了问题。 SignalR 可以与 Require.js 一起使用,事实上我都在一个项目中工作。我想比回答你的问题。
  • 感谢您的回复。你有代码建议吗?我已经在上面列出了我的代码。如果您认为它不正确,您能具体说明您要更改的内容吗?您有 SignalR 和 require.js 工作,但我需要 SignalR、require.js 和 Marionette 模块按照我提供的链接中的规定一起工作。如果你已经这样做了,你能给我一些关于你如何将自动生成的依赖项放入单独的 Marionette 聊天模块的线索吗?这似乎是故障的确切位置。再次感谢。
  • 我的错。我的开发环境 VS 2012 缓存了不好的结果。即使在上面的代码到位之后,仍然会得到未定义的 SignalR。项目干净和清除浏览器缓存和 SignalR 负载。上面的代码是正确的,对我有用。我的包含我的 Marionette 聊天模块的单独文件确实获取了依赖项。非常感谢您的回答。
【解决方案2】:

我使用@raciel-r 的解决方案成功设置了 RequireJS,但我仍然遇到其他 JavaScript 模块(如 karma)的问题,这些模块也被动态代理混淆了。我将信号器代理转换为静态文件,并将其与 RequireJS 一起使用:

  1. 导入Microsoft.AspNet.SignalR.Utils

  2. 运行 packages/Microsoft.AspNet.SignalR.Utils.2.X.X/tools/signalr.exe ghp /path:my/bin /o:path/to/scripts/server.js,其中 /my/bin 是包含带有 SignalR 集线器的程序集的目录。

  3. 将您对/signalr/hubs 的引用替换为server

    requirejs.config({        
    paths: {
         // ...
         "signalr.hubs": "path/to/scripts/server"
    },
    //  ....
    
  4. 如果您使用生成代理的便捷方法,您还必须重写它们(参见How to create a physical file for the SignalR generated proxy

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-23
    • 2016-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多