信号器在IIS 7.5和Edge/IE中错误地反序列化我的对象,foreverFrame坏了吗?

Jar*_*rem 6 asp.net iis signalr knockout-mapping-plugin knockout.js

所以我有一个简单的Signalr/Knockout项目,它使用映射插件将一个简单的对象(带有更多项的数组的项)绑定到我在JS中定义的viewModel:

var someObjectMapping = {
    'MyItemArray': {
        create: function (options) {
            return new MyItemViewModel(options.data);
        }
    }
}

var myItemMapping = {
    'ItemChildren': {
        create: function (options) {
            return new ItemChildViewModel(options.data);
        }
    }
}

var SomeObjectViewModel = function (data) {
    ko.mapping.fromJS(data, someObjectMapping, this);
}

var MyItemViewModel = function (data) {
    ko.mapping.fromJS(data, myItemMapping, this);
}

var ItemChildViewModel = function (data) {
    ko.mapping.fromJS(data, null, this);
}
Run Code Online (Sandbox Code Playgroud)

我使用SignalR的默认设置连接到我的集线器,如下所示:

    var myHubProxy = $.connection.myHub;

    myHubProxy.client.processSomeObject = function(someObject) {
        console.log('SomeObject received');
        var viewModel = new SomeObjectViewModel(someObject);
        ko.applyBindings(viewModel);
    }

    $.connection.hub.start().done(function() {
        console.log('Now connected, connection ID=' + $.connection.hub.id);
        myHubProxy.server.getSomeObject();
    });
Run Code Online (Sandbox Code Playgroud)

当我的对象返回时,knockout应用绑定并处理映射.然后,对象及其子数组自然地在页面上呈现:

<h2 data-bind="text: MyItem"></h2>
<ul data-bind="foreach: MyItemArray">
    <li>
        <span data-bind="text: Name"></span>
        <ul data-bind="foreach: ItemChildren">
            <li data-bind="text: Name"></li>
        </ul>
    </li>
</ul>
Run Code Online (Sandbox Code Playgroud)

现在对于踢球者:这适用于我的本地机器(Win 10,IIS Express),在所有浏览器(Chrome/Firefox/Safari/IE)中,没问题.但是,当我将其发布到IIS 7.5时,它适用于除Internet Explorer 8-10和Microsoft Edge之外的所有浏览器.相同的代码.

当我浏览F12时,我注意到,从IIS中,第一个映射中的create函数获得了一个数组:

iis viewmodel

相反,在第一次休息时,我应该在我的数组中拥有第一个项目,就像在我的本地机器上一样:

本地视图模型

钻取callstack会发现knockout.mapping的createCallback函数中的对象没有被解释为数组,因为它应该:

回调

但是,在我的本地计算机上,它按预期工作:

本地回调

奇怪的是,两件事之一可以解决这个问题:首先,如果我序列化对象,我从SignalR返回,然后在将其绑定到我的淘汰模型之前对其进行解除封装,一切都适用于IIS 7.5中的所有浏览器:

  myHubProxy.client.processSomeObject = function(someObject) {
        console.log('SomeObject received');
        var jsonStr = JSON.stringify(someObject);
        var viewModel = new SomeObjectViewModel(JSON.parse(jsonStr));
        ko.applyBindings(viewModel);
    }
Run Code Online (Sandbox Code Playgroud)

但这会影响性能.

或者,如果我强制SignalR的传输到longPolling,那么所有浏览器中的所有浏览器都适用于IIS 7.5:

    $.connection.hub.start({ transport: "longPolling" }).done(function () {
        console.log('Now connected, connection ID=' + $.connection.hub.id);
        myHubProxy.server.getSomeObject();
    });
Run Code Online (Sandbox Code Playgroud)

但是,我不会拥有WebSockets提供的优于轮询的优势.

IIS 7.5不支持WebSockets

我也可以硬编码我的json并将其与knockout绑定,这在所有浏览器中都能正常工作.

我花了很长时间才发现发生了什么,我一直在努力想出这个问题.奇怪的是,当它运行相同的简单脚本时,它在所有其他浏览器中的IIS 7.5中运行,但IE/Edge.它也适用于所有浏览器IIS 10(非Express),这不是我要发布的服务器的选项.

编辑: Uffe指出IIS 7.5不支持WebSockets.在启用日志记录之后,我看到,对于IIS 7.5,Signalr将转而回归到IE的foreverFrame和其他浏览器的serverSentEvents(在IE中不支持).

我还测试了强制foreverFrame,它使用IIS 10 Express在我的机器上重现了这个问题:

    $.connection.hub.start({ transport: 'foreverFrame'}).done(function () {
        console.log('Now connected, connection ID=' + $.connection.hub.id);
        myHubProxy.server.getSomeObject();
    });
Run Code Online (Sandbox Code Playgroud)

因此,另一种解决方法是在发布到IIS 7.5时完全从传输中跳过foreverFrame,如下所示:

    $.connection.hub.start({ transport: ['serverSentEvents','longPolling']}).done(function () {
        console.log('Now connected, connection ID=' + $.connection.hub.id);
        myHubProxy.server.getSomeObject();
    });
Run Code Online (Sandbox Code Playgroud)

这是一个重现问题的示例项目:https: //onedrive.live.com/redir?resid = D4E23CA0ED671323!1466815&authkey =!AEAEBajrZx3y8e4 &ithint = folder%2csln

Uff*_*ffe 2

在 IIS 7.5 上你永远不会通过 SignalR 获得 WebSockets

请参阅文档- 您将需要 win8/2012 服务器和 IIS8

编辑:很抱歉没有回答有关序列化的问题,但既然你提到你想要 websockets,我认为提及这一点很重要......