2015-07-23 7 views
5

Così ho un progetto semplice Signalr/Knockout che utilizza il plugin mappatura per associare un oggetto semplice (elemento con una serie di altri elementi) per ViewModels ho definito in JS:Signalr deserializza i miei oggetti in modo errato in IIS 7.5 e Edge/IE, foreverFrame rotto?

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

Io uso le impostazioni predefinite di SignalR a connettersi al mio hub in questo modo:

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

Quando il mio oggetto torna, ad eliminazione diretta si applica la rilegatura e la mappatura viene elaborato. Poi l'oggetto e le sue matrici bambini sono naturalmente rese sulla pagina:

<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> 

Ora, per il kicker: Questo funziona in sulla mia macchina locale (Win 10, IIS espresso), in tutti i browser (Chrome/Firefox/Safari/IE), nessun problema. Tuttavia, quando pubblico questo in IIS 7.5, funziona in tutti i browser ad eccezione di Internet Explorer 8-10 e Microsoft Edge. Stesso codice

Quando ho perforare F12 mi accorgo che, da IIS, la funzione di creare nella prima mappatura ottiene una matrice:

iis viewmodel

Quando invece, il primo break, dovrei avere la prima voce il mio allineamento come fa sulla mia macchina locale:

local viewmodel

Foratura lo stack rivela che il genitore oggetto in kN la funzione di createCallback ockout.mapping non viene interpretato come un array come dovrebbe:

iis callback

Tuttavia, sulla mia macchina locale, funziona come previsto:

local callback

Stranamente, uno dei due cose possono risolvere il problema: in primo luogo, se serializzo l'oggetto torno da SignalR e quindi deseralizzi prima di legarlo al mio modello knockout, tutto funziona da tutti i browser da 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); 
    } 

Ma questo può influire sulle prestazioni.

O se forzo il trasporto di SignalR a longPolling, ancora una volta tutto funziona in tutti i browser da IIS 7.5:

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

Ma poi non avrebbe il vantaggio WebSockets fornisce oltre polling.

IIS 7.5 non supporta WebSockets

Posso anche hardcode mia JSON e associarlo con eliminazione diretta, che funziona come previsto in tutti i browser.

Mi ci è voluto un giorno per scoprire cosa stava succedendo e ho cercato di capirlo. È strano che questo funzioni da IIS 7.5 in tutti gli altri browser, ma IE/Edge quando eseguono lo stesso semplice script.Funziona anche con tutti i browser IIS 10 (non-Express), che non è un'opzione per il server che sto pubblicando.

Modifica: Uffe ha sottolineato che IIS 7.5 non supporta WebSockets. Dopo aver abilitato la registrazione, ho visto che, per IIS 7.5, Signalr eseguirà il fallback su foreverFrame per IE e serverSentEvents (which isn't supported in IE) per altri browser.

Ho anche provato costringendo foreverFrame, che riproduceva il problema sulla mia macchina con IIS 10 espresso:

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

Quindi un'altra soluzione potrebbe essere quella di passare foreverFrame dal trasporto del tutto quando la pubblicazione in IIS 7.5 in questo modo:

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

Ecco un progetto di esempio che riproduce il problema: https://onedrive.live.com/redir?resid=D4E23CA0ED671323!1466815&authkey=!AEAEBajrZx3y8e4&ithint=folder%2csln

risposta

1

Lei non potrà mai ottenere WebSockets con SignalR su IIS 7.5

Vedi the docs - Sarà necessario Win8/2012 Server e IIS8

Edit: Ci scusiamo per non rispondere la roba sulla serializzazione, ma dal momento che si parla di voler WebSockets Ho pensato che fosse importante menzionare questo ...

+0

No questo aiuta, in realtà. Non avevo realizzato che IIS 7.5 non supportasse webSockets. Sono in grado di riprodurre il problema in qualsiasi versione di IIS forzando foreverFrame. Ho aggiornato il post per riflettere il problema. Grazie. – Jarem

+0

Questo non sembra risolvere il problema del SignalR che si comporta in modo diverso sul server locale vs server remoto come indicato nella richiesta. Sembra dal post che SignalR + knockout.mapping non funziona in IE (Chrome e Firefox funzionano entrambi) a meno che non si utilizzi un polling lungo, tranne che sull'host locale. –

+0

Non uso mai SignalR, volevo solo aiutare il ragazzo perché pensava di poter ottenere websocket con signalr sotto IIS8 ... – Uffe

1

Il problema è che utilizzando ForeverFrame, l'analisi JSON viene eseguita in un altro frame e l'array risultante non ènel frame corrente, come descritto here.

Per bypassare questo, SignalR (a partire dal 2.1.0) consente di fornire il proprio parser JSON per ForeverFrame:

$.connection.hub.json = { 
    parse: function(text, reviver) { 
     console.log("Parsing JSON"); 
     return window.JSON.parse(text, reviver); 
    }, 
    stringify: function(value, replacer, space) { 
     return window.JSON.stringify(value, replacer, space); 
    } 
}; 

Chiamando window.JSON.parse, ci si assicura che l'array verrà analizzata correttamente.

Problemi correlati