Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Send a request to the server on window unload and connection stop tha…

…t ends the request.

- Fixed some issues with disconnect handling where events were fired by the caller. Instead disconnect events are fired by the receiver.
- Updated javascript client to call new /kill url when connection.stop is invoked. This function will execute synchronous
ajax request to fire the disconnect command.
  • Loading branch information...
commit eda4d1e20307ebee1908fbcfbf07e1ebf5a833bd 1 parent 1f6948c
@davidfowl davidfowl authored
View
32 SignalR/Scripts/jquery.signalR.js
@@ -132,6 +132,11 @@
transport.start(connection, function () {
connection.transport = transport;
$(connection).trigger(events.onStart);
+
+ $(window).unload(function () {
+ connection.stop();
+ });
+
}, function () {
initialize(transports, index + 1);
});
@@ -385,7 +390,18 @@
}
});
},
-
+ ajaxKill: function (connection) {
+ var url = connection.url + "/kill" + "?transport=" + connection.transport.name + "&connectionId=" + window.escape(connection.id);
+ url = this.addQs(url, connection);
+ $.ajax({
+ url: url,
+ async: false,
+ global: false,
+ type: "POST",
+ dataType: connection.ajaxDataType,
+ data: {}
+ });
+ },
processMessages: function (connection, data) {
var $connection = $(connection);
@@ -673,6 +689,8 @@
connection.eventSource = null;
delete connection.eventSource;
}
+
+ transportLogic.ajaxKill(connection);
}
},
@@ -763,6 +781,8 @@
delete connection.frame;
delete connection.frameId;
}
+
+ transportLogic.ajaxKill(connection);
},
getConnection: function (id) {
@@ -850,7 +870,7 @@
}
if (reconnectTimeOut) {
- // If the request failed then we clear the timeout so that the
+ // If the request failed then we clear the timeout so that the
// reconnect event doesn't get fired
clearTimeout(reconnectTimeOut);
}
@@ -873,10 +893,10 @@
that.reconnectDelay);
}
- } (connection));
+ }(connection));
// Now connected
- // There's no good way know when the long poll has actually started so
+ // There's no good way know when the long poll has actually started so
// we assume it only takes around 150ms (max) to start the connection
window.setTimeout(onSuccess, 150);
@@ -895,6 +915,8 @@
connection.pollXhr = null;
delete connection.pollXhr;
}
+
+ transportLogic.ajaxKill(connection);
}
}
};
@@ -914,4 +936,4 @@
$.connection = $.signalR = signalR;
-} (window.jQuery, window));
+}(window.jQuery, window));
View
2  SignalR/Scripts/jquery.signalR.min.js
@@ -6,4 +6,4 @@
* Licensed under the MIT.
* https://github.com/SignalR/SignalR/blob/master/LICENSE.md
*/
-(function(n,t){"use strict";var f,e,i,r,u;if(typeof n!="function")throw"SignalR: jQuery not found. Please ensure jQuery is referenced before the SignalR.js file.";if(!t.JSON)throw"SignalR: No JSON parser found. Please ensure json2.js is referenced before the SignalR.js file if you need to support clients without native JSON parsing support, e.g. IE<8.";i={onStart:"onStart",onStarting:"onStarting",onSending:"onSending",onReceived:"onReceived",onError:"onError",onReconnect:"onReconnect",onDisconnect:"onDisconnect"},r=function(n,i){if(i!==!1){var r;typeof t.console!="undefined"&&(r="["+(new Date).toTimeString()+"] SignalR: "+n,t.console.debug?t.console.debug(r):t.console.log&&t.console.log(r))}},f=function(n,t,i){return new f.fn.init(n,t,i)},f.fn=f.prototype={init:function(n,t,i){this.url=n,this.qs=t,typeof i=="boolean"&&(this.logging=i)},ajaxDataType:"json",logging:!1,reconnectDelay:2e3,start:function(r,u){var e=this,o={transport:"auto",xdomain:!1},h,s=n.Deferred();return e.transport?(s.resolve(e),s.promise()):(n.type(r)==="function"?u=r:n.type(r)==="object"&&(n.extend(o,r),n.type(o.callback)==="function"&&(u=o.callback)),e.ajaxDataType=o.xdomain?"jsonp":"json",n(e).bind(i.onStart,function(){n.type(u)==="function"&&u.call(e),s.resolve(e)}),h=function(t,r){if(r=r||0,r>=t.length){e.transport||s.reject("SignalR: No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.");return}var u=t[r],o=n.type(u)==="object"?u:f.transports[u];o.start(e,function(){e.transport=o,n(e).trigger(i.onStart)},function(){h(t,r+1)})},t.setTimeout(function(){var t=e.url+"/negotiate";n.ajax({url:t,global:!1,cache:!1,type:"GET",data:{},dataType:e.ajaxDataType,error:function(t){n(e).trigger(i.onError,[t]),s.reject("SignalR: Error during negotiation request: "+t)},success:function(t){if(e.appRelativeUrl=t.Url,e.id=t.ConnectionId,e.webSocketServerUrl=t.WebSocketServerUrl,!t.ProtocolVersion||t.ProtocolVersion!=="1.0"){n(e).trigger(i.onError,"SignalR: Incompatible protocol version."),s.reject("SignalR: Incompatible protocol version.");return}n(e).trigger(i.onStarting);var u=[],r=[];n.each(f.transports,function(n){if(n==="webSockets"&&!t.TryWebSockets)return!0;r.push(n)}),n.isArray(o.transport)?n.each(o.transport,function(){var t=this;(n.type(t)==="object"||n.type(t)==="string"&&n.inArray(""+t,r)>=0)&&u.push(n.type(t)==="string"?""+t:t)}):n.type(o.transport)==="object"||n.inArray(o.transport,r)>=0?u.push(o.transport):u=r,h(u)}})},0),s.promise())},starting:function(t){var r=this,u=n(r);return u.bind(i.onStarting,function(){t.call(r),u.unbind(i.onStarting)}),r},send:function(n){var t=this;if(!t.transport)throw"SignalR: Connection must be started before data can be sent. Call .start() before .send()";return t.transport.send(t,n),t},sending:function(t){var r=this;return n(r).bind(i.onSending,function(){t.call(r)}),r},received:function(t){var r=this;return n(r).bind(i.onReceived,function(n,i){t.call(r,i)}),r},error:function(t){var r=this;return n(r).bind(i.onError,function(n,i){t.call(r,i)}),r},disconnected:function(t){var r=this;return n(r).bind(i.onDisconnect,function(){t.call(r)}),r},reconnected:function(t){var r=this;return n(r).bind(i.onReconnect,function(){t.call(r)}),r},stop:function(){var t=this;return t.transport&&(t.transport.stop(t),t.transport=null),delete t.messageId,delete t.groups,n(t).trigger(i.onDisconnect),t},log:r},f.fn.init.prototype=f.fn,u={addQs:function(i,r){return r.qs?typeof r.qs=="object"?i+"&"+n.param(r.qs):typeof r.qs=="string"?i+"&"+r.qs:i+"&"+t.escape(r.qs.toString()):i},getUrl:function(n,i,r,u){var f=n.url,e="transport="+i+"&connectionId="+t.escape(n.id);return n.data&&(e+="&connectionData="+t.escape(n.data)),r?(u&&(f=f+"/reconnect"),n.messageId&&(e+="&messageId="+n.messageId),n.groups&&(e+="&groups="+t.escape(JSON.stringify(n.groups)))):f=f+"/connect",f+="?"+e,f=this.addQs(f,n)},ajaxSend:function(r,u){var f=r.url+"/send?transport="+r.transport.name+"&connectionId="+t.escape(r.id);f=this.addQs(f,r),n.ajax({url:f,global:!1,type:"POST",dataType:r.ajaxDataType,data:{data:u},success:function(t){t&&n(r).trigger(i.onReceived,[t])},error:function(t,u){u!=="abort"&&(u!=="parsererror"||r.ajaxDataType!=="jsonp")&&n(r).trigger(i.onError,[t])}})},processMessages:function(t,u){var f=n(t);if(u){if(u.Disconnect){r("Disconnect command received from server",t.logging),t.stop(),f.trigger(i.onDisconnect);return}u.Messages&&n.each(u.Messages,function(){try{f.trigger(i.onReceived,[this])}catch(u){r("Error raising received "+u,t.logging),n(t).trigger(i.onError,[u])}}),u.MessageId&&(t.messageId=u.MessageId),u.TransportData&&(t.groups=u.TransportData.Groups)}},foreverFrame:{count:0,connections:{}}},f.transports={webSockets:{name:"webSockets",send:function(n,t){n.socket.send(t)},start:function(u,f,e){var o,h=!1,s;if(t.MozWebSocket&&(t.WebSocket=t.MozWebSocket),!t.WebSocket){e();return}u.socket||(u.webSocketServerUrl?o=u.webSocketServerUrl:(s=document.location.protocol==="https:"?"wss://":"ws://",o=s+document.location.host+u.appRelativeUrl),n(u).trigger(i.onSending),o+=u.data?"?connectionData="+u.data+"&transport=webSockets&connectionId="+u.id:"?transport=webSockets&connectionId="+u.id,u.socket=new t.WebSocket(o),u.socket.onopen=function(){h=!0,f&&f()},u.socket.onclose=function(t){h?typeof t.wasClean!="undefined"&&t.wasClean===!1&&n(u).trigger(i.onError):e&&e(),u.socket=null},u.socket.onmessage=function(f){var e=t.JSON.parse(f.data),o;e&&(o=n(u),e.Messages?n.each(e.Messages,function(){try{o.trigger(i.onReceived,[this])}catch(n){r("Error raising received "+n,u.logging)}}):o.trigger(i.onReceived,[e]))})},stop:function(n){n.socket!==null&&(n.socket.close(),n.socket=null)}},serverSentEvents:{name:"serverSentEvents",timeOut:3e3,start:function(f,e,o){var s=this,l=!1,c=n(f),h=!e,v,a;if(f.eventSource&&f.stop(),!t.EventSource){o&&o();return}c.trigger(i.onSending),v=u.getUrl(f,this.name,h);try{f.eventSource=new t.EventSource(v)}catch(y){r("EventSource failed trying to connect with error "+y.Message,f.logging),o?o():(c.trigger(i.onError,[y]),h&&(r("EventSource reconnecting",f.logging),s.reconnect(f)));return}a=t.setTimeout(function(){l===!1&&(r("EventSource timed out trying to connect",f.logging),o&&o(),h?(r("EventSource reconnecting",f.logging),s.reconnect(f)):s.stop(f))},s.timeOut),f.eventSource.addEventListener("open",function(){r("EventSource connected",f.logging),a&&t.clearTimeout(a),l===!1&&(l=!0,e&&e(),h&&c.trigger(i.onReconnect))},!1),f.eventSource.addEventListener("message",function(n){n.data!=="initialized"&&u.processMessages(f,t.JSON.parse(n.data))},!1),f.eventSource.addEventListener("error",function(n){if(!l){o&&o();return}r("EventSource readyState: "+f.eventSource.readyState,f.logging),n.eventPhase===t.EventSource.CLOSED?f.eventSource.readyState===t.EventSource.CONNECTING?(r("EventSource reconnecting due to the server connection ending",f.logging),s.reconnect(f)):(r("EventSource closed",f.logging),s.stop(f)):(r("EventSource error",f.logging),c.trigger(i.onError))},!1)},reconnect:function(n){var i=this;t.setTimeout(function(){i.stop(n),i.start(n)},n.reconnectDelay)},send:function(n,t){u.ajaxSend(n,t)},stop:function(n){n&&n.eventSource&&(n.eventSource.close(),n.eventSource=null,delete n.eventSource)}},foreverFrame:{name:"foreverFrame",timeOut:3e3,start:function(f,e,o){var h=this,l=u.foreverFrame.count+=1,c,a,s=n("<iframe data-signalr-connection-id='"+f.id+"' style='position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;'></iframe>");if(t.EventSource){o&&o();return}n(f).trigger(i.onSending),c=u.getUrl(f,this.name),c+="&frameId="+l,s.prop("src",c),u.foreverFrame.connections[l]=f,s.bind("readystatechange",function(){n.inArray(this.readyState,["loaded","complete"])>=0&&(r("Forever frame iframe readyState changed to "+this.readyState+", reconnecting",f.logging),h.reconnect(f))}),f.frame=s[0],f.frameId=l,e&&(f.onSuccess=e),n("body").append(s),a=t.setTimeout(function(){f.onSuccess&&(h.stop(f),o&&o())},h.timeOut)},reconnect:function(n){var i=this;t.setTimeout(function(){var r=n.frame,t=u.getUrl(n,i.name,!0)+"&frameId="+n.frameId;r.src=t},n.reconnectDelay)},send:function(n,t){u.ajaxSend(n,t)},receive:u.processMessages,stop:function(t){t.frame&&(t.frame.stop?t.frame.stop():t.frame.document&&t.frame.document.execCommand&&t.frame.document.execCommand("Stop"),n(t.frame).remove(),delete u.foreverFrame.connections[t.frameId],t.frame=null,t.frameId=null,delete t.frame,delete t.frameId)},getConnection:function(n){return u.foreverFrame.connections[n]},started:function(t){t.onSuccess?(t.onSuccess(),t.onSuccess=null,delete t.onSuccess):n(t).trigger(i.onReconnect)}},longPolling:{name:"longPolling",reconnectDelay:3e3,start:function(r,f){var o=this;r.pollXhr&&r.stop(),r.messageId=null,t.setTimeout(function(){(function e(f,s){n(f).trigger(i.onSending);var a=f.messageId,l=a===null,v=u.getUrl(f,o.name,!l,s),c=null,h=!1;f.pollXhr=n.ajax({url:v,global:!1,type:"GET",dataType:r.ajaxDataType,success:function(r){var c=0,o=!1;s===!0&&h===!1&&(n(f).trigger(i.onReconnect),h=!0),u.processMessages(f,r),r&&r.TransportData&&n.type(r.TransportData.LongPollDelay)==="number"&&(c=r.TransportData.LongPollDelay),r&&r.TimedOut&&(o=r.TimedOut),c>0?t.setTimeout(function(){e(f,o)},c):e(f,o)},error:function(u,o){o!=="abort"&&(c&&clearTimeout(c),n(f).trigger(i.onError,[u]),t.setTimeout(function(){e(f,!0)},r.reconnectDelay))}}),s===!0&&(c=t.setTimeout(function(){h===!1&&(n(f).trigger(i.onReconnect),h=!0)},o.reconnectDelay))})(r),t.setTimeout(f,150)},250)},send:function(n,t){u.ajaxSend(n,t)},stop:function(n){n.pollXhr&&(n.pollXhr.abort(),n.pollXhr=null,delete n.pollXhr)}}},f.noConflict=function(){return n.connection===f&&(n.connection=e),f},n.connection&&(e=n.connection),n.connection=n.signalR=f})(window.jQuery,window)
+(function(n,t){"use strict";var f,e,i,u,r;if(typeof n!="function")throw"SignalR: jQuery not found. Please ensure jQuery is referenced before the SignalR.js file.";if(!t.JSON)throw"SignalR: No JSON parser found. Please ensure json2.js is referenced before the SignalR.js file if you need to support clients without native JSON parsing support, e.g. IE<8.";i={onStart:"onStart",onStarting:"onStarting",onSending:"onSending",onReceived:"onReceived",onError:"onError",onReconnect:"onReconnect",onDisconnect:"onDisconnect"},u=function(n,i){if(i!==!1){var r;typeof t.console!="undefined"&&(r="["+(new Date).toTimeString()+"] SignalR: "+n,t.console.debug?t.console.debug(r):t.console.log&&t.console.log(r))}},f=function(n,t,i){return new f.fn.init(n,t,i)},f.fn=f.prototype={init:function(n,t,i){this.url=n,this.qs=t,typeof i=="boolean"&&(this.logging=i)},ajaxDataType:"json",logging:!1,reconnectDelay:2e3,start:function(r,u){var e=this,o={transport:"auto",xdomain:!1},h,s=n.Deferred();return e.transport?(s.resolve(e),s.promise()):(n.type(r)==="function"?u=r:n.type(r)==="object"&&(n.extend(o,r),n.type(o.callback)==="function"&&(u=o.callback)),e.ajaxDataType=o.xdomain?"jsonp":"json",n(e).bind(i.onStart,function(){n.type(u)==="function"&&u.call(e),s.resolve(e)}),h=function(r,u){if(u=u||0,u>=r.length){e.transport||s.reject("SignalR: No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.");return}var o=r[u],c=n.type(o)==="object"?o:f.transports[o];c.start(e,function(){e.transport=c,n(e).trigger(i.onStart),n(t).unload(function(){e.stop()})},function(){h(r,u+1)})},t.setTimeout(function(){var t=e.url+"/negotiate";n.ajax({url:t,global:!1,cache:!1,type:"GET",data:{},dataType:e.ajaxDataType,error:function(t){n(e).trigger(i.onError,[t]),s.reject("SignalR: Error during negotiation request: "+t)},success:function(t){if(e.appRelativeUrl=t.Url,e.id=t.ConnectionId,e.webSocketServerUrl=t.WebSocketServerUrl,!t.ProtocolVersion||t.ProtocolVersion!=="1.0"){n(e).trigger(i.onError,"SignalR: Incompatible protocol version."),s.reject("SignalR: Incompatible protocol version.");return}n(e).trigger(i.onStarting);var u=[],r=[];n.each(f.transports,function(n){if(n==="webSockets"&&!t.TryWebSockets)return!0;r.push(n)}),n.isArray(o.transport)?n.each(o.transport,function(){var t=this;(n.type(t)==="object"||n.type(t)==="string"&&n.inArray(""+t,r)>=0)&&u.push(n.type(t)==="string"?""+t:t)}):n.type(o.transport)==="object"||n.inArray(o.transport,r)>=0?u.push(o.transport):u=r,h(u)}})},0),s.promise())},starting:function(t){var r=this,u=n(r);return u.bind(i.onStarting,function(){t.call(r),u.unbind(i.onStarting)}),r},send:function(n){var t=this;if(!t.transport)throw"SignalR: Connection must be started before data can be sent. Call .start() before .send()";return t.transport.send(t,n),t},sending:function(t){var r=this;return n(r).bind(i.onSending,function(){t.call(r)}),r},received:function(t){var r=this;return n(r).bind(i.onReceived,function(n,i){t.call(r,i)}),r},error:function(t){var r=this;return n(r).bind(i.onError,function(n,i){t.call(r,i)}),r},disconnected:function(t){var r=this;return n(r).bind(i.onDisconnect,function(){t.call(r)}),r},reconnected:function(t){var r=this;return n(r).bind(i.onReconnect,function(){t.call(r)}),r},stop:function(){var t=this;return t.transport&&(t.transport.stop(t),t.transport=null),delete t.messageId,delete t.groups,n(t).trigger(i.onDisconnect),t},log:u},f.fn.init.prototype=f.fn,r={addQs:function(i,r){return r.qs?typeof r.qs=="object"?i+"&"+n.param(r.qs):typeof r.qs=="string"?i+"&"+r.qs:i+"&"+t.escape(r.qs.toString()):i},getUrl:function(n,i,r,u){var f=n.url,e="transport="+i+"&connectionId="+t.escape(n.id);return n.data&&(e+="&connectionData="+t.escape(n.data)),r?(u&&(f=f+"/reconnect"),n.messageId&&(e+="&messageId="+n.messageId),n.groups&&(e+="&groups="+t.escape(JSON.stringify(n.groups)))):f=f+"/connect",f+="?"+e,f=this.addQs(f,n)},ajaxSend:function(r,u){var f=r.url+"/send?transport="+r.transport.name+"&connectionId="+t.escape(r.id);f=this.addQs(f,r),n.ajax({url:f,global:!1,type:"POST",dataType:r.ajaxDataType,data:{data:u},success:function(t){t&&n(r).trigger(i.onReceived,[t])},error:function(t,u){u!=="abort"&&(u!=="parsererror"||r.ajaxDataType!=="jsonp")&&n(r).trigger(i.onError,[t])}})},ajaxKill:function(i){var r=i.url+"/kill?transport="+i.transport.name+"&connectionId="+t.escape(i.id);r=this.addQs(r,i),n.ajax({url:r,async:!1,global:!1,type:"POST",dataType:i.ajaxDataType,data:{}})},processMessages:function(t,r){var f=n(t);if(r){if(r.Disconnect){u("Disconnect command received from server",t.logging),t.stop(),f.trigger(i.onDisconnect);return}r.Messages&&n.each(r.Messages,function(){try{f.trigger(i.onReceived,[this])}catch(r){u("Error raising received "+r,t.logging),n(t).trigger(i.onError,[r])}}),r.MessageId&&(t.messageId=r.MessageId),r.TransportData&&(t.groups=r.TransportData.Groups)}},foreverFrame:{count:0,connections:{}}},f.transports={webSockets:{name:"webSockets",send:function(n,t){n.socket.send(t)},start:function(r,f,e){var o,h=!1,s;if(t.MozWebSocket&&(t.WebSocket=t.MozWebSocket),!t.WebSocket){e();return}r.socket||(r.webSocketServerUrl?o=r.webSocketServerUrl:(s=document.location.protocol==="https:"?"wss://":"ws://",o=s+document.location.host+r.appRelativeUrl),n(r).trigger(i.onSending),o+=r.data?"?connectionData="+r.data+"&transport=webSockets&connectionId="+r.id:"?transport=webSockets&connectionId="+r.id,r.socket=new t.WebSocket(o),r.socket.onopen=function(){h=!0,f&&f()},r.socket.onclose=function(t){h?typeof t.wasClean!="undefined"&&t.wasClean===!1&&n(r).trigger(i.onError):e&&e(),r.socket=null},r.socket.onmessage=function(f){var e=t.JSON.parse(f.data),o;e&&(o=n(r),e.Messages?n.each(e.Messages,function(){try{o.trigger(i.onReceived,[this])}catch(n){u("Error raising received "+n,r.logging)}}):o.trigger(i.onReceived,[e]))})},stop:function(n){n.socket!==null&&(n.socket.close(),n.socket=null)}},serverSentEvents:{name:"serverSentEvents",timeOut:3e3,start:function(f,e,o){var s=this,l=!1,c=n(f),h=!e,v,a;if(f.eventSource&&f.stop(),!t.EventSource){o&&o();return}c.trigger(i.onSending),v=r.getUrl(f,this.name,h);try{f.eventSource=new t.EventSource(v)}catch(y){u("EventSource failed trying to connect with error "+y.Message,f.logging),o?o():(c.trigger(i.onError,[y]),h&&(u("EventSource reconnecting",f.logging),s.reconnect(f)));return}a=t.setTimeout(function(){l===!1&&(u("EventSource timed out trying to connect",f.logging),o&&o(),h?(u("EventSource reconnecting",f.logging),s.reconnect(f)):s.stop(f))},s.timeOut),f.eventSource.addEventListener("open",function(){u("EventSource connected",f.logging),a&&t.clearTimeout(a),l===!1&&(l=!0,e&&e(),h&&c.trigger(i.onReconnect))},!1),f.eventSource.addEventListener("message",function(n){n.data!=="initialized"&&r.processMessages(f,t.JSON.parse(n.data))},!1),f.eventSource.addEventListener("error",function(n){if(!l){o&&o();return}u("EventSource readyState: "+f.eventSource.readyState,f.logging),n.eventPhase===t.EventSource.CLOSED?f.eventSource.readyState===t.EventSource.CONNECTING?(u("EventSource reconnecting due to the server connection ending",f.logging),s.reconnect(f)):(u("EventSource closed",f.logging),s.stop(f)):(u("EventSource error",f.logging),c.trigger(i.onError))},!1)},reconnect:function(n){var i=this;t.setTimeout(function(){i.stop(n),i.start(n)},n.reconnectDelay)},send:function(n,t){r.ajaxSend(n,t)},stop:function(n){n&&n.eventSource&&(n.eventSource.close(),n.eventSource=null,delete n.eventSource),r.ajaxKill(n)}},foreverFrame:{name:"foreverFrame",timeOut:3e3,start:function(f,e,o){var h=this,l=r.foreverFrame.count+=1,c,a,s=n("<iframe data-signalr-connection-id='"+f.id+"' style='position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;'></iframe>");if(t.EventSource){o&&o();return}n(f).trigger(i.onSending),c=r.getUrl(f,this.name),c+="&frameId="+l,s.prop("src",c),r.foreverFrame.connections[l]=f,s.bind("readystatechange",function(){n.inArray(this.readyState,["loaded","complete"])>=0&&(u("Forever frame iframe readyState changed to "+this.readyState+", reconnecting",f.logging),h.reconnect(f))}),f.frame=s[0],f.frameId=l,e&&(f.onSuccess=e),n("body").append(s),a=t.setTimeout(function(){f.onSuccess&&(h.stop(f),o&&o())},h.timeOut)},reconnect:function(n){var i=this;t.setTimeout(function(){var u=n.frame,t=r.getUrl(n,i.name,!0)+"&frameId="+n.frameId;u.src=t},n.reconnectDelay)},send:function(n,t){r.ajaxSend(n,t)},receive:r.processMessages,stop:function(t){t.frame&&(t.frame.stop?t.frame.stop():t.frame.document&&t.frame.document.execCommand&&t.frame.document.execCommand("Stop"),n(t.frame).remove(),delete r.foreverFrame.connections[t.frameId],t.frame=null,t.frameId=null,delete t.frame,delete t.frameId),r.ajaxKill(t)},getConnection:function(n){return r.foreverFrame.connections[n]},started:function(t){t.onSuccess?(t.onSuccess(),t.onSuccess=null,delete t.onSuccess):n(t).trigger(i.onReconnect)}},longPolling:{name:"longPolling",reconnectDelay:3e3,start:function(u,f){var o=this;u.pollXhr&&u.stop(),u.messageId=null,t.setTimeout(function(){(function e(f,s){n(f).trigger(i.onSending);var a=f.messageId,l=a===null,v=r.getUrl(f,o.name,!l,s),c=null,h=!1;f.pollXhr=n.ajax({url:v,global:!1,type:"GET",dataType:u.ajaxDataType,success:function(u){var c=0,o=!1;s===!0&&h===!1&&(n(f).trigger(i.onReconnect),h=!0),r.processMessages(f,u),u&&u.TransportData&&n.type(u.TransportData.LongPollDelay)==="number"&&(c=u.TransportData.LongPollDelay),u&&u.TimedOut&&(o=u.TimedOut),c>0?t.setTimeout(function(){e(f,o)},c):e(f,o)},error:function(r,o){o!=="abort"&&(c&&clearTimeout(c),n(f).trigger(i.onError,[r]),t.setTimeout(function(){e(f,!0)},u.reconnectDelay))}}),s===!0&&(c=t.setTimeout(function(){h===!1&&(n(f).trigger(i.onReconnect),h=!0)},o.reconnectDelay))})(u),t.setTimeout(f,150)},250)},send:function(n,t){r.ajaxSend(n,t)},stop:function(n){n.pollXhr&&(n.pollXhr.abort(),n.pollXhr=null,delete n.pollXhr),r.ajaxKill(n)}}},f.noConflict=function(){return n.connection===f&&(n.connection=e),f},n.connection&&(e=n.connection),n.connection=n.signalR=f})(window.jQuery,window)
View
18 SignalR/Transports/ForeverTransport.cs
@@ -1,6 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Threading.Tasks;
using SignalR.Hosting;
@@ -55,7 +53,7 @@ protected virtual void OnSending(string payload)
Sending(payload);
}
}
-
+
protected static void OnReceiving(string data)
{
if (Receiving != null)
@@ -86,6 +84,10 @@ protected Task ProcessRequestCore(ITransportConnection connection)
{
return ProcessSendRequest();
}
+ else if (IsKillRequest)
+ {
+ return Disconnect();
+ }
else
{
if (IsConnectRequest)
@@ -200,6 +202,11 @@ private void ProcessMessagesImpl(TaskCompletionSource<object> taskCompletetionSo
Task sendTask = Send(response);
if (response.Disconnect || response.TimedOut)
{
+ if (response.Disconnect)
+ {
+ OnDisconnect();
+ }
+
// Signal the tcs when the task is done
return sendTask.Then(tcs => tcs.SetResult(null), taskCompletetionSource);
}
@@ -224,6 +231,11 @@ private void ProcessMessagesImpl(TaskCompletionSource<object> taskCompletetionSo
return;
}
+ if (!IsTimedOut)
+ {
+ OnDisconnect();
+ }
+
taskCompletetionSource.SetResult(null);
return;
}
View
18 SignalR/Transports/LongPollingTransport.cs
@@ -43,7 +43,7 @@ public override TimeSpan DisconnectThreshold
{
get { return TimeSpan.FromMilliseconds(LongPollDelay); }
}
-
+
protected override bool IsConnectRequest
{
get
@@ -110,6 +110,10 @@ public Task ProcessRequest(ITransportConnection connection)
{
return ProcessSendRequest();
}
+ else if (IsKillRequest)
+ {
+ return Disconnect();
+ }
else
{
if (IsConnectRequest)
@@ -142,7 +146,7 @@ public virtual Task Send(PersistentResponse response)
public virtual Task Send(object value)
{
var payload = _jsonSerializer.Stringify(value);
-
+
if (IsJsonp)
{
payload = Json.CreateJsonpCallback(JsonpCallback, payload);
@@ -207,7 +211,15 @@ private Task ProcessReceiveRequest(ITransportConnection connection, Action postR
postReceive();
}
- return receiveTask.Then(response => Send(response));
+ return receiveTask.Then(response =>
+ {
+ if (response.Disconnect)
+ {
+ OnDisconnect();
+ }
+
+ Send(response);
+ });
}
private PersistentResponse AddTransportData(PersistentResponse response)
View
38 SignalR/Transports/TransportDisconnectBase.cs
@@ -24,7 +24,7 @@ public TransportDisconnectBase(HostContext context, IJsonSerializer jsonSerializ
_jsonSerializer = jsonSerializer;
_heartBeat = heartBeat;
_timeoutTokenSource = new CancellationTokenSource();
-
+
// Register the callback to cancel this connection
var hostShutdownToken = context.HostShutdownToken();
if (hostShutdownToken != CancellationToken.None)
@@ -105,36 +105,32 @@ protected virtual bool IsConnectRequest
}
}
+ protected bool IsKillRequest
+ {
+ get
+ {
+ return Context.Request.Url.LocalPath.EndsWith("/kill", StringComparison.OrdinalIgnoreCase);
+ }
+ }
+
public Task Disconnect()
{
+ return Connection.Close();
+ }
+
+ public Task OnDisconnect()
+ {
if (Interlocked.Exchange(ref _isDisconnected, 1) == 0)
{
var disconnected = Disconnected; // copy before invoking event to avoid race
if (disconnected != null)
{
Debug.WriteLine("TransportDisconnectBase: Disconnect fired for connection {0}", (object)ConnectionId);
- return disconnected()
- .ContinueWith(t =>
- {
- if (t.IsFaulted)
- {
- // Observe & trace any exception
- Trace.TraceError("SignalR: Error during transport disconnect: {0}", t.Exception);
- }
- return Connection.Close();
- })
- .FastUnwrap();
- }
- else
- {
- return Connection.Close();
+ return disconnected().Catch();
}
}
- else
- {
- // somebody else already fired the Disconnect event
- return TaskAsyncHelper.Empty;
- }
+
+ return TaskAsyncHelper.Empty;
}
public void Timeout()
View
32 samples/SignalR.Hosting.AspNet.Samples/Scripts/jquery.signalR.js
@@ -132,6 +132,11 @@
transport.start(connection, function () {
connection.transport = transport;
$(connection).trigger(events.onStart);
+
+ $(window).unload(function () {
+ connection.stop();
+ });
+
}, function () {
initialize(transports, index + 1);
});
@@ -385,7 +390,18 @@
}
});
},
-
+ ajaxKill: function (connection) {
+ var url = connection.url + "/kill" + "?transport=" + connection.transport.name + "&connectionId=" + window.escape(connection.id);
+ url = this.addQs(url, connection);
+ $.ajax({
+ url: url,
+ async: false,
+ global: false,
+ type: "POST",
+ dataType: connection.ajaxDataType,
+ data: {}
+ });
+ },
processMessages: function (connection, data) {
var $connection = $(connection);
@@ -673,6 +689,8 @@
connection.eventSource = null;
delete connection.eventSource;
}
+
+ transportLogic.ajaxKill(connection);
}
},
@@ -763,6 +781,8 @@
delete connection.frame;
delete connection.frameId;
}
+
+ transportLogic.ajaxKill(connection);
},
getConnection: function (id) {
@@ -850,7 +870,7 @@
}
if (reconnectTimeOut) {
- // If the request failed then we clear the timeout so that the
+ // If the request failed then we clear the timeout so that the
// reconnect event doesn't get fired
clearTimeout(reconnectTimeOut);
}
@@ -873,10 +893,10 @@
that.reconnectDelay);
}
- } (connection));
+ }(connection));
// Now connected
- // There's no good way know when the long poll has actually started so
+ // There's no good way know when the long poll has actually started so
// we assume it only takes around 150ms (max) to start the connection
window.setTimeout(onSuccess, 150);
@@ -895,6 +915,8 @@
connection.pollXhr = null;
delete connection.pollXhr;
}
+
+ transportLogic.ajaxKill(connection);
}
}
};
@@ -914,4 +936,4 @@
$.connection = $.signalR = signalR;
-} (window.jQuery, window));
+}(window.jQuery, window));
View
2  samples/SignalR.Hosting.AspNet.Samples/Scripts/jquery.signalR.min.js
@@ -6,4 +6,4 @@
* Licensed under the MIT.
* https://github.com/SignalR/SignalR/blob/master/LICENSE.md
*/
-(function(n,t){"use strict";var f,e,i,r,u;if(typeof n!="function")throw"SignalR: jQuery not found. Please ensure jQuery is referenced before the SignalR.js file.";if(!t.JSON)throw"SignalR: No JSON parser found. Please ensure json2.js is referenced before the SignalR.js file if you need to support clients without native JSON parsing support, e.g. IE<8.";i={onStart:"onStart",onStarting:"onStarting",onSending:"onSending",onReceived:"onReceived",onError:"onError",onReconnect:"onReconnect",onDisconnect:"onDisconnect"},r=function(n,i){if(i!==!1){var r;typeof t.console!="undefined"&&(r="["+(new Date).toTimeString()+"] SignalR: "+n,t.console.debug?t.console.debug(r):t.console.log&&t.console.log(r))}},f=function(n,t,i){return new f.fn.init(n,t,i)},f.fn=f.prototype={init:function(n,t,i){this.url=n,this.qs=t,typeof i=="boolean"&&(this.logging=i)},ajaxDataType:"json",logging:!1,reconnectDelay:2e3,start:function(r,u){var e=this,o={transport:"auto",xdomain:!1},h,s=n.Deferred();return e.transport?(s.resolve(e),s.promise()):(n.type(r)==="function"?u=r:n.type(r)==="object"&&(n.extend(o,r),n.type(o.callback)==="function"&&(u=o.callback)),e.ajaxDataType=o.xdomain?"jsonp":"json",n(e).bind(i.onStart,function(){n.type(u)==="function"&&u.call(e),s.resolve(e)}),h=function(t,r){if(r=r||0,r>=t.length){e.transport||s.reject("SignalR: No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.");return}var u=t[r],o=n.type(u)==="object"?u:f.transports[u];o.start(e,function(){e.transport=o,n(e).trigger(i.onStart)},function(){h(t,r+1)})},t.setTimeout(function(){var t=e.url+"/negotiate";n.ajax({url:t,global:!1,cache:!1,type:"GET",data:{},dataType:e.ajaxDataType,error:function(t){n(e).trigger(i.onError,[t]),s.reject("SignalR: Error during negotiation request: "+t)},success:function(t){if(e.appRelativeUrl=t.Url,e.id=t.ConnectionId,e.webSocketServerUrl=t.WebSocketServerUrl,!t.ProtocolVersion||t.ProtocolVersion!=="1.0"){n(e).trigger(i.onError,"SignalR: Incompatible protocol version."),s.reject("SignalR: Incompatible protocol version.");return}n(e).trigger(i.onStarting);var u=[],r=[];n.each(f.transports,function(n){if(n==="webSockets"&&!t.TryWebSockets)return!0;r.push(n)}),n.isArray(o.transport)?n.each(o.transport,function(){var t=this;(n.type(t)==="object"||n.type(t)==="string"&&n.inArray(""+t,r)>=0)&&u.push(n.type(t)==="string"?""+t:t)}):n.type(o.transport)==="object"||n.inArray(o.transport,r)>=0?u.push(o.transport):u=r,h(u)}})},0),s.promise())},starting:function(t){var r=this,u=n(r);return u.bind(i.onStarting,function(){t.call(r),u.unbind(i.onStarting)}),r},send:function(n){var t=this;if(!t.transport)throw"SignalR: Connection must be started before data can be sent. Call .start() before .send()";return t.transport.send(t,n),t},sending:function(t){var r=this;return n(r).bind(i.onSending,function(){t.call(r)}),r},received:function(t){var r=this;return n(r).bind(i.onReceived,function(n,i){t.call(r,i)}),r},error:function(t){var r=this;return n(r).bind(i.onError,function(n,i){t.call(r,i)}),r},disconnected:function(t){var r=this;return n(r).bind(i.onDisconnect,function(){t.call(r)}),r},reconnected:function(t){var r=this;return n(r).bind(i.onReconnect,function(){t.call(r)}),r},stop:function(){var t=this;return t.transport&&(t.transport.stop(t),t.transport=null),delete t.messageId,delete t.groups,n(t).trigger(i.onDisconnect),t},log:r},f.fn.init.prototype=f.fn,u={addQs:function(i,r){return r.qs?typeof r.qs=="object"?i+"&"+n.param(r.qs):typeof r.qs=="string"?i+"&"+r.qs:i+"&"+t.escape(r.qs.toString()):i},getUrl:function(n,i,r,u){var f=n.url,e="transport="+i+"&connectionId="+t.escape(n.id);return n.data&&(e+="&connectionData="+t.escape(n.data)),r?(u&&(f=f+"/reconnect"),n.messageId&&(e+="&messageId="+n.messageId),n.groups&&(e+="&groups="+t.escape(JSON.stringify(n.groups)))):f=f+"/connect",f+="?"+e,f=this.addQs(f,n)},ajaxSend:function(r,u){var f=r.url+"/send?transport="+r.transport.name+"&connectionId="+t.escape(r.id);f=this.addQs(f,r),n.ajax({url:f,global:!1,type:"POST",dataType:r.ajaxDataType,data:{data:u},success:function(t){t&&n(r).trigger(i.onReceived,[t])},error:function(t,u){u!=="abort"&&(u!=="parsererror"||r.ajaxDataType!=="jsonp")&&n(r).trigger(i.onError,[t])}})},processMessages:function(t,u){var f=n(t);if(u){if(u.Disconnect){r("Disconnect command received from server",t.logging),t.stop(),f.trigger(i.onDisconnect);return}u.Messages&&n.each(u.Messages,function(){try{f.trigger(i.onReceived,[this])}catch(u){r("Error raising received "+u,t.logging),n(t).trigger(i.onError,[u])}}),u.MessageId&&(t.messageId=u.MessageId),u.TransportData&&(t.groups=u.TransportData.Groups)}},foreverFrame:{count:0,connections:{}}},f.transports={webSockets:{name:"webSockets",send:function(n,t){n.socket.send(t)},start:function(u,f,e){var o,h=!1,s;if(t.MozWebSocket&&(t.WebSocket=t.MozWebSocket),!t.WebSocket){e();return}u.socket||(u.webSocketServerUrl?o=u.webSocketServerUrl:(s=document.location.protocol==="https:"?"wss://":"ws://",o=s+document.location.host+u.appRelativeUrl),n(u).trigger(i.onSending),o+=u.data?"?connectionData="+u.data+"&transport=webSockets&connectionId="+u.id:"?transport=webSockets&connectionId="+u.id,u.socket=new t.WebSocket(o),u.socket.onopen=function(){h=!0,f&&f()},u.socket.onclose=function(t){h?typeof t.wasClean!="undefined"&&t.wasClean===!1&&n(u).trigger(i.onError):e&&e(),u.socket=null},u.socket.onmessage=function(f){var e=t.JSON.parse(f.data),o;e&&(o=n(u),e.Messages?n.each(e.Messages,function(){try{o.trigger(i.onReceived,[this])}catch(n){r("Error raising received "+n,u.logging)}}):o.trigger(i.onReceived,[e]))})},stop:function(n){n.socket!==null&&(n.socket.close(),n.socket=null)}},serverSentEvents:{name:"serverSentEvents",timeOut:3e3,start:function(f,e,o){var s=this,l=!1,c=n(f),h=!e,v,a;if(f.eventSource&&f.stop(),!t.EventSource){o&&o();return}c.trigger(i.onSending),v=u.getUrl(f,this.name,h);try{f.eventSource=new t.EventSource(v)}catch(y){r("EventSource failed trying to connect with error "+y.Message,f.logging),o?o():(c.trigger(i.onError,[y]),h&&(r("EventSource reconnecting",f.logging),s.reconnect(f)));return}a=t.setTimeout(function(){l===!1&&(r("EventSource timed out trying to connect",f.logging),o&&o(),h?(r("EventSource reconnecting",f.logging),s.reconnect(f)):s.stop(f))},s.timeOut),f.eventSource.addEventListener("open",function(){r("EventSource connected",f.logging),a&&t.clearTimeout(a),l===!1&&(l=!0,e&&e(),h&&c.trigger(i.onReconnect))},!1),f.eventSource.addEventListener("message",function(n){n.data!=="initialized"&&u.processMessages(f,t.JSON.parse(n.data))},!1),f.eventSource.addEventListener("error",function(n){if(!l){o&&o();return}r("EventSource readyState: "+f.eventSource.readyState,f.logging),n.eventPhase===t.EventSource.CLOSED?f.eventSource.readyState===t.EventSource.CONNECTING?(r("EventSource reconnecting due to the server connection ending",f.logging),s.reconnect(f)):(r("EventSource closed",f.logging),s.stop(f)):(r("EventSource error",f.logging),c.trigger(i.onError))},!1)},reconnect:function(n){var i=this;t.setTimeout(function(){i.stop(n),i.start(n)},n.reconnectDelay)},send:function(n,t){u.ajaxSend(n,t)},stop:function(n){n&&n.eventSource&&(n.eventSource.close(),n.eventSource=null,delete n.eventSource)}},foreverFrame:{name:"foreverFrame",timeOut:3e3,start:function(f,e,o){var h=this,l=u.foreverFrame.count+=1,c,a,s=n("<iframe data-signalr-connection-id='"+f.id+"' style='position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;'></iframe>");if(t.EventSource){o&&o();return}n(f).trigger(i.onSending),c=u.getUrl(f,this.name),c+="&frameId="+l,s.prop("src",c),u.foreverFrame.connections[l]=f,s.bind("readystatechange",function(){n.inArray(this.readyState,["loaded","complete"])>=0&&(r("Forever frame iframe readyState changed to "+this.readyState+", reconnecting",f.logging),h.reconnect(f))}),f.frame=s[0],f.frameId=l,e&&(f.onSuccess=e),n("body").append(s),a=t.setTimeout(function(){f.onSuccess&&(h.stop(f),o&&o())},h.timeOut)},reconnect:function(n){var i=this;t.setTimeout(function(){var r=n.frame,t=u.getUrl(n,i.name,!0)+"&frameId="+n.frameId;r.src=t},n.reconnectDelay)},send:function(n,t){u.ajaxSend(n,t)},receive:u.processMessages,stop:function(t){t.frame&&(t.frame.stop?t.frame.stop():t.frame.document&&t.frame.document.execCommand&&t.frame.document.execCommand("Stop"),n(t.frame).remove(),delete u.foreverFrame.connections[t.frameId],t.frame=null,t.frameId=null,delete t.frame,delete t.frameId)},getConnection:function(n){return u.foreverFrame.connections[n]},started:function(t){t.onSuccess?(t.onSuccess(),t.onSuccess=null,delete t.onSuccess):n(t).trigger(i.onReconnect)}},longPolling:{name:"longPolling",reconnectDelay:3e3,start:function(r,f){var o=this;r.pollXhr&&r.stop(),r.messageId=null,t.setTimeout(function(){(function e(f,s){n(f).trigger(i.onSending);var a=f.messageId,l=a===null,v=u.getUrl(f,o.name,!l,s),c=null,h=!1;f.pollXhr=n.ajax({url:v,global:!1,type:"GET",dataType:r.ajaxDataType,success:function(r){var c=0,o=!1;s===!0&&h===!1&&(n(f).trigger(i.onReconnect),h=!0),u.processMessages(f,r),r&&r.TransportData&&n.type(r.TransportData.LongPollDelay)==="number"&&(c=r.TransportData.LongPollDelay),r&&r.TimedOut&&(o=r.TimedOut),c>0?t.setTimeout(function(){e(f,o)},c):e(f,o)},error:function(u,o){o!=="abort"&&(c&&clearTimeout(c),n(f).trigger(i.onError,[u]),t.setTimeout(function(){e(f,!0)},r.reconnectDelay))}}),s===!0&&(c=t.setTimeout(function(){h===!1&&(n(f).trigger(i.onReconnect),h=!0)},o.reconnectDelay))})(r),t.setTimeout(f,150)},250)},send:function(n,t){u.ajaxSend(n,t)},stop:function(n){n.pollXhr&&(n.pollXhr.abort(),n.pollXhr=null,delete n.pollXhr)}}},f.noConflict=function(){return n.connection===f&&(n.connection=e),f},n.connection&&(e=n.connection),n.connection=n.signalR=f})(window.jQuery,window)
+(function(n,t){"use strict";var f,e,i,u,r;if(typeof n!="function")throw"SignalR: jQuery not found. Please ensure jQuery is referenced before the SignalR.js file.";if(!t.JSON)throw"SignalR: No JSON parser found. Please ensure json2.js is referenced before the SignalR.js file if you need to support clients without native JSON parsing support, e.g. IE<8.";i={onStart:"onStart",onStarting:"onStarting",onSending:"onSending",onReceived:"onReceived",onError:"onError",onReconnect:"onReconnect",onDisconnect:"onDisconnect"},u=function(n,i){if(i!==!1){var r;typeof t.console!="undefined"&&(r="["+(new Date).toTimeString()+"] SignalR: "+n,t.console.debug?t.console.debug(r):t.console.log&&t.console.log(r))}},f=function(n,t,i){return new f.fn.init(n,t,i)},f.fn=f.prototype={init:function(n,t,i){this.url=n,this.qs=t,typeof i=="boolean"&&(this.logging=i)},ajaxDataType:"json",logging:!1,reconnectDelay:2e3,start:function(r,u){var e=this,o={transport:"auto",xdomain:!1},h,s=n.Deferred();return e.transport?(s.resolve(e),s.promise()):(n.type(r)==="function"?u=r:n.type(r)==="object"&&(n.extend(o,r),n.type(o.callback)==="function"&&(u=o.callback)),e.ajaxDataType=o.xdomain?"jsonp":"json",n(e).bind(i.onStart,function(){n.type(u)==="function"&&u.call(e),s.resolve(e)}),h=function(r,u){if(u=u||0,u>=r.length){e.transport||s.reject("SignalR: No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.");return}var o=r[u],c=n.type(o)==="object"?o:f.transports[o];c.start(e,function(){e.transport=c,n(e).trigger(i.onStart),n(t).unload(function(){e.stop()})},function(){h(r,u+1)})},t.setTimeout(function(){var t=e.url+"/negotiate";n.ajax({url:t,global:!1,cache:!1,type:"GET",data:{},dataType:e.ajaxDataType,error:function(t){n(e).trigger(i.onError,[t]),s.reject("SignalR: Error during negotiation request: "+t)},success:function(t){if(e.appRelativeUrl=t.Url,e.id=t.ConnectionId,e.webSocketServerUrl=t.WebSocketServerUrl,!t.ProtocolVersion||t.ProtocolVersion!=="1.0"){n(e).trigger(i.onError,"SignalR: Incompatible protocol version."),s.reject("SignalR: Incompatible protocol version.");return}n(e).trigger(i.onStarting);var u=[],r=[];n.each(f.transports,function(n){if(n==="webSockets"&&!t.TryWebSockets)return!0;r.push(n)}),n.isArray(o.transport)?n.each(o.transport,function(){var t=this;(n.type(t)==="object"||n.type(t)==="string"&&n.inArray(""+t,r)>=0)&&u.push(n.type(t)==="string"?""+t:t)}):n.type(o.transport)==="object"||n.inArray(o.transport,r)>=0?u.push(o.transport):u=r,h(u)}})},0),s.promise())},starting:function(t){var r=this,u=n(r);return u.bind(i.onStarting,function(){t.call(r),u.unbind(i.onStarting)}),r},send:function(n){var t=this;if(!t.transport)throw"SignalR: Connection must be started before data can be sent. Call .start() before .send()";return t.transport.send(t,n),t},sending:function(t){var r=this;return n(r).bind(i.onSending,function(){t.call(r)}),r},received:function(t){var r=this;return n(r).bind(i.onReceived,function(n,i){t.call(r,i)}),r},error:function(t){var r=this;return n(r).bind(i.onError,function(n,i){t.call(r,i)}),r},disconnected:function(t){var r=this;return n(r).bind(i.onDisconnect,function(){t.call(r)}),r},reconnected:function(t){var r=this;return n(r).bind(i.onReconnect,function(){t.call(r)}),r},stop:function(){var t=this;return t.transport&&(t.transport.stop(t),t.transport=null),delete t.messageId,delete t.groups,n(t).trigger(i.onDisconnect),t},log:u},f.fn.init.prototype=f.fn,r={addQs:function(i,r){return r.qs?typeof r.qs=="object"?i+"&"+n.param(r.qs):typeof r.qs=="string"?i+"&"+r.qs:i+"&"+t.escape(r.qs.toString()):i},getUrl:function(n,i,r,u){var f=n.url,e="transport="+i+"&connectionId="+t.escape(n.id);return n.data&&(e+="&connectionData="+t.escape(n.data)),r?(u&&(f=f+"/reconnect"),n.messageId&&(e+="&messageId="+n.messageId),n.groups&&(e+="&groups="+t.escape(JSON.stringify(n.groups)))):f=f+"/connect",f+="?"+e,f=this.addQs(f,n)},ajaxSend:function(r,u){var f=r.url+"/send?transport="+r.transport.name+"&connectionId="+t.escape(r.id);f=this.addQs(f,r),n.ajax({url:f,global:!1,type:"POST",dataType:r.ajaxDataType,data:{data:u},success:function(t){t&&n(r).trigger(i.onReceived,[t])},error:function(t,u){u!=="abort"&&(u!=="parsererror"||r.ajaxDataType!=="jsonp")&&n(r).trigger(i.onError,[t])}})},ajaxKill:function(i){var r=i.url+"/kill?transport="+i.transport.name+"&connectionId="+t.escape(i.id);r=this.addQs(r,i),n.ajax({url:r,async:!1,global:!1,type:"POST",dataType:i.ajaxDataType,data:{}})},processMessages:function(t,r){var f=n(t);if(r){if(r.Disconnect){u("Disconnect command received from server",t.logging),t.stop(),f.trigger(i.onDisconnect);return}r.Messages&&n.each(r.Messages,function(){try{f.trigger(i.onReceived,[this])}catch(r){u("Error raising received "+r,t.logging),n(t).trigger(i.onError,[r])}}),r.MessageId&&(t.messageId=r.MessageId),r.TransportData&&(t.groups=r.TransportData.Groups)}},foreverFrame:{count:0,connections:{}}},f.transports={webSockets:{name:"webSockets",send:function(n,t){n.socket.send(t)},start:function(r,f,e){var o,h=!1,s;if(t.MozWebSocket&&(t.WebSocket=t.MozWebSocket),!t.WebSocket){e();return}r.socket||(r.webSocketServerUrl?o=r.webSocketServerUrl:(s=document.location.protocol==="https:"?"wss://":"ws://",o=s+document.location.host+r.appRelativeUrl),n(r).trigger(i.onSending),o+=r.data?"?connectionData="+r.data+"&transport=webSockets&connectionId="+r.id:"?transport=webSockets&connectionId="+r.id,r.socket=new t.WebSocket(o),r.socket.onopen=function(){h=!0,f&&f()},r.socket.onclose=function(t){h?typeof t.wasClean!="undefined"&&t.wasClean===!1&&n(r).trigger(i.onError):e&&e(),r.socket=null},r.socket.onmessage=function(f){var e=t.JSON.parse(f.data),o;e&&(o=n(r),e.Messages?n.each(e.Messages,function(){try{o.trigger(i.onReceived,[this])}catch(n){u("Error raising received "+n,r.logging)}}):o.trigger(i.onReceived,[e]))})},stop:function(n){n.socket!==null&&(n.socket.close(),n.socket=null)}},serverSentEvents:{name:"serverSentEvents",timeOut:3e3,start:function(f,e,o){var s=this,l=!1,c=n(f),h=!e,v,a;if(f.eventSource&&f.stop(),!t.EventSource){o&&o();return}c.trigger(i.onSending),v=r.getUrl(f,this.name,h);try{f.eventSource=new t.EventSource(v)}catch(y){u("EventSource failed trying to connect with error "+y.Message,f.logging),o?o():(c.trigger(i.onError,[y]),h&&(u("EventSource reconnecting",f.logging),s.reconnect(f)));return}a=t.setTimeout(function(){l===!1&&(u("EventSource timed out trying to connect",f.logging),o&&o(),h?(u("EventSource reconnecting",f.logging),s.reconnect(f)):s.stop(f))},s.timeOut),f.eventSource.addEventListener("open",function(){u("EventSource connected",f.logging),a&&t.clearTimeout(a),l===!1&&(l=!0,e&&e(),h&&c.trigger(i.onReconnect))},!1),f.eventSource.addEventListener("message",function(n){n.data!=="initialized"&&r.processMessages(f,t.JSON.parse(n.data))},!1),f.eventSource.addEventListener("error",function(n){if(!l){o&&o();return}u("EventSource readyState: "+f.eventSource.readyState,f.logging),n.eventPhase===t.EventSource.CLOSED?f.eventSource.readyState===t.EventSource.CONNECTING?(u("EventSource reconnecting due to the server connection ending",f.logging),s.reconnect(f)):(u("EventSource closed",f.logging),s.stop(f)):(u("EventSource error",f.logging),c.trigger(i.onError))},!1)},reconnect:function(n){var i=this;t.setTimeout(function(){i.stop(n),i.start(n)},n.reconnectDelay)},send:function(n,t){r.ajaxSend(n,t)},stop:function(n){n&&n.eventSource&&(n.eventSource.close(),n.eventSource=null,delete n.eventSource),r.ajaxKill(n)}},foreverFrame:{name:"foreverFrame",timeOut:3e3,start:function(f,e,o){var h=this,l=r.foreverFrame.count+=1,c,a,s=n("<iframe data-signalr-connection-id='"+f.id+"' style='position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;'></iframe>");if(t.EventSource){o&&o();return}n(f).trigger(i.onSending),c=r.getUrl(f,this.name),c+="&frameId="+l,s.prop("src",c),r.foreverFrame.connections[l]=f,s.bind("readystatechange",function(){n.inArray(this.readyState,["loaded","complete"])>=0&&(u("Forever frame iframe readyState changed to "+this.readyState+", reconnecting",f.logging),h.reconnect(f))}),f.frame=s[0],f.frameId=l,e&&(f.onSuccess=e),n("body").append(s),a=t.setTimeout(function(){f.onSuccess&&(h.stop(f),o&&o())},h.timeOut)},reconnect:function(n){var i=this;t.setTimeout(function(){var u=n.frame,t=r.getUrl(n,i.name,!0)+"&frameId="+n.frameId;u.src=t},n.reconnectDelay)},send:function(n,t){r.ajaxSend(n,t)},receive:r.processMessages,stop:function(t){t.frame&&(t.frame.stop?t.frame.stop():t.frame.document&&t.frame.document.execCommand&&t.frame.document.execCommand("Stop"),n(t.frame).remove(),delete r.foreverFrame.connections[t.frameId],t.frame=null,t.frameId=null,delete t.frame,delete t.frameId),r.ajaxKill(t)},getConnection:function(n){return r.foreverFrame.connections[n]},started:function(t){t.onSuccess?(t.onSuccess(),t.onSuccess=null,delete t.onSuccess):n(t).trigger(i.onReconnect)}},longPolling:{name:"longPolling",reconnectDelay:3e3,start:function(u,f){var o=this;u.pollXhr&&u.stop(),u.messageId=null,t.setTimeout(function(){(function e(f,s){n(f).trigger(i.onSending);var a=f.messageId,l=a===null,v=r.getUrl(f,o.name,!l,s),c=null,h=!1;f.pollXhr=n.ajax({url:v,global:!1,type:"GET",dataType:u.ajaxDataType,success:function(u){var c=0,o=!1;s===!0&&h===!1&&(n(f).trigger(i.onReconnect),h=!0),r.processMessages(f,u),u&&u.TransportData&&n.type(u.TransportData.LongPollDelay)==="number"&&(c=u.TransportData.LongPollDelay),u&&u.TimedOut&&(o=u.TimedOut),c>0?t.setTimeout(function(){e(f,o)},c):e(f,o)},error:function(r,o){o!=="abort"&&(c&&clearTimeout(c),n(f).trigger(i.onError,[r]),t.setTimeout(function(){e(f,!0)},u.reconnectDelay))}}),s===!0&&(c=t.setTimeout(function(){h===!1&&(n(f).trigger(i.onReconnect),h=!0)},o.reconnectDelay))})(u),t.setTimeout(f,150)},250)},send:function(n,t){r.ajaxSend(n,t)},stop:function(n){n.pollXhr&&(n.pollXhr.abort(),n.pollXhr=null,delete n.pollXhr),r.ajaxKill(n)}}},f.noConflict=function(){return n.connection===f&&(n.connection=e),f},n.connection&&(e=n.connection),n.connection=n.signalR=f})(window.jQuery,window)
View
32 samples/SignalR.Hosting.Owin.Samples/Content/Scripts/jquery.signalR.js
@@ -132,6 +132,11 @@
transport.start(connection, function () {
connection.transport = transport;
$(connection).trigger(events.onStart);
+
+ $(window).unload(function () {
+ connection.stop();
+ });
+
}, function () {
initialize(transports, index + 1);
});
@@ -385,7 +390,18 @@
}
});
},
-
+ ajaxKill: function (connection) {
+ var url = connection.url + "/kill" + "?transport=" + connection.transport.name + "&connectionId=" + window.escape(connection.id);
+ url = this.addQs(url, connection);
+ $.ajax({
+ url: url,
+ async: false,
+ global: false,
+ type: "POST",
+ dataType: connection.ajaxDataType,
+ data: {}
+ });
+ },
processMessages: function (connection, data) {
var $connection = $(connection);
@@ -673,6 +689,8 @@
connection.eventSource = null;
delete connection.eventSource;
}
+
+ transportLogic.ajaxKill(connection);
}
},
@@ -763,6 +781,8 @@
delete connection.frame;
delete connection.frameId;
}
+
+ transportLogic.ajaxKill(connection);
},
getConnection: function (id) {
@@ -850,7 +870,7 @@
}
if (reconnectTimeOut) {
- // If the request failed then we clear the timeout so that the
+ // If the request failed then we clear the timeout so that the
// reconnect event doesn't get fired
clearTimeout(reconnectTimeOut);
}
@@ -873,10 +893,10 @@
that.reconnectDelay);
}
- } (connection));
+ }(connection));
// Now connected
- // There's no good way know when the long poll has actually started so
+ // There's no good way know when the long poll has actually started so
// we assume it only takes around 150ms (max) to start the connection
window.setTimeout(onSuccess, 150);
@@ -895,6 +915,8 @@
connection.pollXhr = null;
delete connection.pollXhr;
}
+
+ transportLogic.ajaxKill(connection);
}
}
};
@@ -914,4 +936,4 @@
$.connection = $.signalR = signalR;
-} (window.jQuery, window));
+}(window.jQuery, window));
View
2  samples/SignalR.Hosting.Owin.Samples/Content/Scripts/jquery.signalR.min.js
@@ -6,4 +6,4 @@
* Licensed under the MIT.
* https://github.com/SignalR/SignalR/blob/master/LICENSE.md
*/
-(function(n,t){"use strict";var f,e,i,r,u;if(typeof n!="function")throw"SignalR: jQuery not found. Please ensure jQuery is referenced before the SignalR.js file.";if(!t.JSON)throw"SignalR: No JSON parser found. Please ensure json2.js is referenced before the SignalR.js file if you need to support clients without native JSON parsing support, e.g. IE<8.";i={onStart:"onStart",onStarting:"onStarting",onSending:"onSending",onReceived:"onReceived",onError:"onError",onReconnect:"onReconnect",onDisconnect:"onDisconnect"},r=function(n,i){if(i!==!1){var r;typeof t.console!="undefined"&&(r="["+(new Date).toTimeString()+"] SignalR: "+n,t.console.debug?t.console.debug(r):t.console.log&&t.console.log(r))}},f=function(n,t,i){return new f.fn.init(n,t,i)},f.fn=f.prototype={init:function(n,t,i){this.url=n,this.qs=t,typeof i=="boolean"&&(this.logging=i)},ajaxDataType:"json",logging:!1,reconnectDelay:2e3,start:function(r,u){var e=this,o={transport:"auto",xdomain:!1},h,s=n.Deferred();return e.transport?(s.resolve(e),s.promise()):(n.type(r)==="function"?u=r:n.type(r)==="object"&&(n.extend(o,r),n.type(o.callback)==="function"&&(u=o.callback)),e.ajaxDataType=o.xdomain?"jsonp":"json",n(e).bind(i.onStart,function(){n.type(u)==="function"&&u.call(e),s.resolve(e)}),h=function(t,r){if(r=r||0,r>=t.length){e.transport||s.reject("SignalR: No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.");return}var u=t[r],o=n.type(u)==="object"?u:f.transports[u];o.start(e,function(){e.transport=o,n(e).trigger(i.onStart)},function(){h(t,r+1)})},t.setTimeout(function(){var t=e.url+"/negotiate";n.ajax({url:t,global:!1,cache:!1,type:"GET",data:{},dataType:e.ajaxDataType,error:function(t){n(e).trigger(i.onError,[t]),s.reject("SignalR: Error during negotiation request: "+t)},success:function(t){if(e.appRelativeUrl=t.Url,e.id=t.ConnectionId,e.webSocketServerUrl=t.WebSocketServerUrl,!t.ProtocolVersion||t.ProtocolVersion!=="1.0"){n(e).trigger(i.onError,"SignalR: Incompatible protocol version."),s.reject("SignalR: Incompatible protocol version.");return}n(e).trigger(i.onStarting);var u=[],r=[];n.each(f.transports,function(n){if(n==="webSockets"&&!t.TryWebSockets)return!0;r.push(n)}),n.isArray(o.transport)?n.each(o.transport,function(){var t=this;(n.type(t)==="object"||n.type(t)==="string"&&n.inArray(""+t,r)>=0)&&u.push(n.type(t)==="string"?""+t:t)}):n.type(o.transport)==="object"||n.inArray(o.transport,r)>=0?u.push(o.transport):u=r,h(u)}})},0),s.promise())},starting:function(t){var r=this,u=n(r);return u.bind(i.onStarting,function(){t.call(r),u.unbind(i.onStarting)}),r},send:function(n){var t=this;if(!t.transport)throw"SignalR: Connection must be started before data can be sent. Call .start() before .send()";return t.transport.send(t,n),t},sending:function(t){var r=this;return n(r).bind(i.onSending,function(){t.call(r)}),r},received:function(t){var r=this;return n(r).bind(i.onReceived,function(n,i){t.call(r,i)}),r},error:function(t){var r=this;return n(r).bind(i.onError,function(n,i){t.call(r,i)}),r},disconnected:function(t){var r=this;return n(r).bind(i.onDisconnect,function(){t.call(r)}),r},reconnected:function(t){var r=this;return n(r).bind(i.onReconnect,function(){t.call(r)}),r},stop:function(){var t=this;return t.transport&&(t.transport.stop(t),t.transport=null),delete t.messageId,delete t.groups,n(t).trigger(i.onDisconnect),t},log:r},f.fn.init.prototype=f.fn,u={addQs:function(i,r){return r.qs?typeof r.qs=="object"?i+"&"+n.param(r.qs):typeof r.qs=="string"?i+"&"+r.qs:i+"&"+t.escape(r.qs.toString()):i},getUrl:function(n,i,r,u){var f=n.url,e="transport="+i+"&connectionId="+t.escape(n.id);return n.data&&(e+="&connectionData="+t.escape(n.data)),r?(u&&(f=f+"/reconnect"),n.messageId&&(e+="&messageId="+n.messageId),n.groups&&(e+="&groups="+t.escape(JSON.stringify(n.groups)))):f=f+"/connect",f+="?"+e,f=this.addQs(f,n)},ajaxSend:function(r,u){var f=r.url+"/send?transport="+r.transport.name+"&connectionId="+t.escape(r.id);f=this.addQs(f,r),n.ajax({url:f,global:!1,type:"POST",dataType:r.ajaxDataType,data:{data:u},success:function(t){t&&n(r).trigger(i.onReceived,[t])},error:function(t,u){u!=="abort"&&(u!=="parsererror"||r.ajaxDataType!=="jsonp")&&n(r).trigger(i.onError,[t])}})},processMessages:function(t,u){var f=n(t);if(u){if(u.Disconnect){r("Disconnect command received from server",t.logging),t.stop(),f.trigger(i.onDisconnect);return}u.Messages&&n.each(u.Messages,function(){try{f.trigger(i.onReceived,[this])}catch(u){r("Error raising received "+u,t.logging),n(t).trigger(i.onError,[u])}}),u.MessageId&&(t.messageId=u.MessageId),u.TransportData&&(t.groups=u.TransportData.Groups)}},foreverFrame:{count:0,connections:{}}},f.transports={webSockets:{name:"webSockets",send:function(n,t){n.socket.send(t)},start:function(u,f,e){var o,h=!1,s;if(t.MozWebSocket&&(t.WebSocket=t.MozWebSocket),!t.WebSocket){e();return}u.socket||(u.webSocketServerUrl?o=u.webSocketServerUrl:(s=document.location.protocol==="https:"?"wss://":"ws://",o=s+document.location.host+u.appRelativeUrl),n(u).trigger(i.onSending),o+=u.data?"?connectionData="+u.data+"&transport=webSockets&connectionId="+u.id:"?transport=webSockets&connectionId="+u.id,u.socket=new t.WebSocket(o),u.socket.onopen=function(){h=!0,f&&f()},u.socket.onclose=function(t){h?typeof t.wasClean!="undefined"&&t.wasClean===!1&&n(u).trigger(i.onError):e&&e(),u.socket=null},u.socket.onmessage=function(f){var e=t.JSON.parse(f.data),o;e&&(o=n(u),e.Messages?n.each(e.Messages,function(){try{o.trigger(i.onReceived,[this])}catch(n){r("Error raising received "+n,u.logging)}}):o.trigger(i.onReceived,[e]))})},stop:function(n){n.socket!==null&&(n.socket.close(),n.socket=null)}},serverSentEvents:{name:"serverSentEvents",timeOut:3e3,start:function(f,e,o){var s=this,l=!1,c=n(f),h=!e,v,a;if(f.eventSource&&f.stop(),!t.EventSource){o&&o();return}c.trigger(i.onSending),v=u.getUrl(f,this.name,h);try{f.eventSource=new t.EventSource(v)}catch(y){r("EventSource failed trying to connect with error "+y.Message,f.logging),o?o():(c.trigger(i.onError,[y]),h&&(r("EventSource reconnecting",f.logging),s.reconnect(f)));return}a=t.setTimeout(function(){l===!1&&(r("EventSource timed out trying to connect",f.logging),o&&o(),h?(r("EventSource reconnecting",f.logging),s.reconnect(f)):s.stop(f))},s.timeOut),f.eventSource.addEventListener("open",function(){r("EventSource connected",f.logging),a&&t.clearTimeout(a),l===!1&&(l=!0,e&&e(),h&&c.trigger(i.onReconnect))},!1),f.eventSource.addEventListener("message",function(n){n.data!=="initialized"&&u.processMessages(f,t.JSON.parse(n.data))},!1),f.eventSource.addEventListener("error",function(n){if(!l){o&&o();return}r("EventSource readyState: "+f.eventSource.readyState,f.logging),n.eventPhase===t.EventSource.CLOSED?f.eventSource.readyState===t.EventSource.CONNECTING?(r("EventSource reconnecting due to the server connection ending",f.logging),s.reconnect(f)):(r("EventSource closed",f.logging),s.stop(f)):(r("EventSource error",f.logging),c.trigger(i.onError))},!1)},reconnect:function(n){var i=this;t.setTimeout(function(){i.stop(n),i.start(n)},n.reconnectDelay)},send:function(n,t){u.ajaxSend(n,t)},stop:function(n){n&&n.eventSource&&(n.eventSource.close(),n.eventSource=null,delete n.eventSource)}},foreverFrame:{name:"foreverFrame",timeOut:3e3,start:function(f,e,o){var h=this,l=u.foreverFrame.count+=1,c,a,s=n("<iframe data-signalr-connection-id='"+f.id+"' style='position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;'></iframe>");if(t.EventSource){o&&o();return}n(f).trigger(i.onSending),c=u.getUrl(f,this.name),c+="&frameId="+l,s.prop("src",c),u.foreverFrame.connections[l]=f,s.bind("readystatechange",function(){n.inArray(this.readyState,["loaded","complete"])>=0&&(r("Forever frame iframe readyState changed to "+this.readyState+", reconnecting",f.logging),h.reconnect(f))}),f.frame=s[0],f.frameId=l,e&&(f.onSuccess=e),n("body").append(s),a=t.setTimeout(function(){f.onSuccess&&(h.stop(f),o&&o())},h.timeOut)},reconnect:function(n){var i=this;t.setTimeout(function(){var r=n.frame,t=u.getUrl(n,i.name,!0)+"&frameId="+n.frameId;r.src=t},n.reconnectDelay)},send:function(n,t){u.ajaxSend(n,t)},receive:u.processMessages,stop:function(t){t.frame&&(t.frame.stop?t.frame.stop():t.frame.document&&t.frame.document.execCommand&&t.frame.document.execCommand("Stop"),n(t.frame).remove(),delete u.foreverFrame.connections[t.frameId],t.frame=null,t.frameId=null,delete t.frame,delete t.frameId)},getConnection:function(n){return u.foreverFrame.connections[n]},started:function(t){t.onSuccess?(t.onSuccess(),t.onSuccess=null,delete t.onSuccess):n(t).trigger(i.onReconnect)}},longPolling:{name:"longPolling",reconnectDelay:3e3,start:function(r,f){var o=this;r.pollXhr&&r.stop(),r.messageId=null,t.setTimeout(function(){(function e(f,s){n(f).trigger(i.onSending);var a=f.messageId,l=a===null,v=u.getUrl(f,o.name,!l,s),c=null,h=!1;f.pollXhr=n.ajax({url:v,global:!1,type:"GET",dataType:r.ajaxDataType,success:function(r){var c=0,o=!1;s===!0&&h===!1&&(n(f).trigger(i.onReconnect),h=!0),u.processMessages(f,r),r&&r.TransportData&&n.type(r.TransportData.LongPollDelay)==="number"&&(c=r.TransportData.LongPollDelay),r&&r.TimedOut&&(o=r.TimedOut),c>0?t.setTimeout(function(){e(f,o)},c):e(f,o)},error:function(u,o){o!=="abort"&&(c&&clearTimeout(c),n(f).trigger(i.onError,[u]),t.setTimeout(function(){e(f,!0)},r.reconnectDelay))}}),s===!0&&(c=t.setTimeout(function(){h===!1&&(n(f).trigger(i.onReconnect),h=!0)},o.reconnectDelay))})(r),t.setTimeout(f,150)},250)},send:function(n,t){u.ajaxSend(n,t)},stop:function(n){n.pollXhr&&(n.pollXhr.abort(),n.pollXhr=null,delete n.pollXhr)}}},f.noConflict=function(){return n.connection===f&&(n.connection=e),f},n.connection&&(e=n.connection),n.connection=n.signalR=f})(window.jQuery,window)
+(function(n,t){"use strict";var f,e,i,u,r;if(typeof n!="function")throw"SignalR: jQuery not found. Please ensure jQuery is referenced before the SignalR.js file.";if(!t.JSON)throw"SignalR: No JSON parser found. Please ensure json2.js is referenced before the SignalR.js file if you need to support clients without native JSON parsing support, e.g. IE<8.";i={onStart:"onStart",onStarting:"onStarting",onSending:"onSending",onReceived:"onReceived",onError:"onError",onReconnect:"onReconnect",onDisconnect:"onDisconnect"},u=function(n,i){if(i!==!1){var r;typeof t.console!="undefined"&&(r="["+(new Date).toTimeString()+"] SignalR: "+n,t.console.debug?t.console.debug(r):t.console.log&&t.console.log(r))}},f=function(n,t,i){return new f.fn.init(n,t,i)},f.fn=f.prototype={init:function(n,t,i){this.url=n,this.qs=t,typeof i=="boolean"&&(this.logging=i)},ajaxDataType:"json",logging:!1,reconnectDelay:2e3,start:function(r,u){var e=this,o={transport:"auto",xdomain:!1},h,s=n.Deferred();return e.transport?(s.resolve(e),s.promise()):(n.type(r)==="function"?u=r:n.type(r)==="object"&&(n.extend(o,r),n.type(o.callback)==="function"&&(u=o.callback)),e.ajaxDataType=o.xdomain?"jsonp":"json",n(e).bind(i.onStart,function(){n.type(u)==="function"&&u.call(e),s.resolve(e)}),h=function(r,u){if(u=u||0,u>=r.length){e.transport||s.reject("SignalR: No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.");return}var o=r[u],c=n.type(o)==="object"?o:f.transports[o];c.start(e,function(){e.transport=c,n(e).trigger(i.onStart),n(t).unload(function(){e.stop()})},function(){h(r,u+1)})},t.setTimeout(function(){var t=e.url+"/negotiate";n.ajax({url:t,global:!1,cache:!1,type:"GET",data:{},dataType:e.ajaxDataType,error:function(t){n(e).trigger(i.onError,[t]),s.reject("SignalR: Error during negotiation request: "+t)},success:function(t){if(e.appRelativeUrl=t.Url,e.id=t.ConnectionId,e.webSocketServerUrl=t.WebSocketServerUrl,!t.ProtocolVersion||t.ProtocolVersion!=="1.0"){n(e).trigger(i.onError,"SignalR: Incompatible protocol version."),s.reject("SignalR: Incompatible protocol version.");return}n(e).trigger(i.onStarting);var u=[],r=[];n.each(f.transports,function(n){if(n==="webSockets"&&!t.TryWebSockets)return!0;r.push(n)}),n.isArray(o.transport)?n.each(o.transport,function(){var t=this;(n.type(t)==="object"||n.type(t)==="string"&&n.inArray(""+t,r)>=0)&&u.push(n.type(t)==="string"?""+t:t)}):n.type(o.transport)==="object"||n.inArray(o.transport,r)>=0?u.push(o.transport):u=r,h(u)}})},0),s.promise())},starting:function(t){var r=this,u=n(r);return u.bind(i.onStarting,function(){t.call(r),u.unbind(i.onStarting)}),r},send:function(n){var t=this;if(!t.transport)throw"SignalR: Connection must be started before data can be sent. Call .start() before .send()";return t.transport.send(t,n),t},sending:function(t){var r=this;return n(r).bind(i.onSending,function(){t.call(r)}),r},received:function(t){var r=this;return n(r).bind(i.onReceived,function(n,i){t.call(r,i)}),r},error:function(t){var r=this;return n(r).bind(i.onError,function(n,i){t.call(r,i)}),r},disconnected:function(t){var r=this;return n(r).bind(i.onDisconnect,function(){t.call(r)}),r},reconnected:function(t){var r=this;return n(r).bind(i.onReconnect,function(){t.call(r)}),r},stop:function(){var t=this;return t.transport&&(t.transport.stop(t),t.transport=null),delete t.messageId,delete t.groups,n(t).trigger(i.onDisconnect),t},log:u},f.fn.init.prototype=f.fn,r={addQs:function(i,r){return r.qs?typeof r.qs=="object"?i+"&"+n.param(r.qs):typeof r.qs=="string"?i+"&"+r.qs:i+"&"+t.escape(r.qs.toString()):i},getUrl:function(n,i,r,u){var f=n.url,e="transport="+i+"&connectionId="+t.escape(n.id);return n.data&&(e+="&connectionData="+t.escape(n.data)),r?(u&&(f=f+"/reconnect"),n.messageId&&(e+="&messageId="+n.messageId),n.groups&&(e+="&groups="+t.escape(JSON.stringify(n.groups)))):f=f+"/connect",f+="?"+e,f=this.addQs(f,n)},ajaxSend:function(r,u){var f=r.url+"/send?transport="+r.transport.name+"&connectionId="+t.escape(r.id);f=this.addQs(f,r),n.ajax({url:f,global:!1,type:"POST",dataType:r.ajaxDataType,data:{data:u},success:function(t){t&&n(r).trigger(i.onReceived,[t])},error:function(t,u){u!=="abort"&&(u!=="parsererror"||r.ajaxDataType!=="jsonp")&&n(r).trigger(i.onError,[t])}})},ajaxKill:function(i){var r=i.url+"/kill?transport="+i.transport.name+"&connectionId="+t.escape(i.id);r=this.addQs(r,i),n.ajax({url:r,async:!1,global:!1,type:"POST",dataType:i.ajaxDataType,data:{}})},processMessages:function(t,r){var f=n(t);if(r){if(r.Disconnect){u("Disconnect command received from server",t.logging),t.stop(),f.trigger(i.onDisconnect);return}r.Messages&&n.each(r.Messages,function(){try{f.trigger(i.onReceived,[this])}catch(r){u("Error raising received "+r,t.logging),n(t).trigger(i.onError,[r])}}),r.MessageId&&(t.messageId=r.MessageId),r.TransportData&&(t.groups=r.TransportData.Groups)}},foreverFrame:{count:0,connections:{}}},f.transports={webSockets:{name:"webSockets",send:function(n,t){n.socket.send(t)},start:function(r,f,e){var o,h=!1,s;if(t.MozWebSocket&&(t.WebSocket=t.MozWebSocket),!t.WebSocket){e();return}r.socket||(r.webSocketServerUrl?o=r.webSocketServerUrl:(s=document.location.protocol==="https:"?"wss://":"ws://",o=s+document.location.host+r.appRelativeUrl),n(r).trigger(i.onSending),o+=r.data?"?connectionData="+r.data+"&transport=webSockets&connectionId="+r.id:"?transport=webSockets&connectionId="+r.id,r.socket=new t.WebSocket(o),r.socket.onopen=function(){h=!0,f&&f()},r.socket.onclose=function(t){h?typeof t.wasClean!="undefined"&&t.wasClean===!1&&n(r).trigger(i.onError):e&&e(),r.socket=null},r.socket.onmessage=function(f){var e=t.JSON.parse(f.data),o;e&&(o=n(r),e.Messages?n.each(e.Messages,function(){try{o.trigger(i.onReceived,[this])}catch(n){u("Error raising received "+n,r.logging)}}):o.trigger(i.onReceived,[e]))})},stop:function(n){n.socket!==null&&(n.socket.close(),n.socket=null)}},serverSentEvents:{name:"serverSentEvents",timeOut:3e3,start:function(f,e,o){var s=this,l=!1,c=n(f),h=!e,v,a;if(f.eventSource&&f.stop(),!t.EventSource){o&&o();return}c.trigger(i.onSending),v=r.getUrl(f,this.name,h);try{f.eventSource=new t.EventSource(v)}catch(y){u("EventSource failed trying to connect with error "+y.Message,f.logging),o?o():(c.trigger(i.onError,[y]),h&&(u("EventSource reconnecting",f.logging),s.reconnect(f)));return}a=t.setTimeout(function(){l===!1&&(u("EventSource timed out trying to connect",f.logging),o&&o(),h?(u("EventSource reconnecting",f.logging),s.reconnect(f)):s.stop(f))},s.timeOut),f.eventSource.addEventListener("open",function(){u("EventSource connected",f.logging),a&&t.clearTimeout(a),l===!1&&(l=!0,e&&e(),h&&c.trigger(i.onReconnect))},!1),f.eventSource.addEventListener("message",function(n){n.data!=="initialized"&&r.processMessages(f,t.JSON.parse(n.data))},!1),f.eventSource.addEventListener("error",function(n){if(!l){o&&o();return}u("EventSource readyState: "+f.eventSource.readyState,f.logging),n.eventPhase===t.EventSource.CLOSED?f.eventSource.readyState===t.EventSource.CONNECTING?(u("EventSource reconnecting due to the server connection ending",f.logging),s.reconnect(f)):(u("EventSource closed",f.logging),s.stop(f)):(u("EventSource error",f.logging),c.trigger(i.onError))},!1)},reconnect:function(n){var i=this;t.setTimeout(function(){i.stop(n),i.start(n)},n.reconnectDelay)},send:function(n,t){r.ajaxSend(n,t)},stop:function(n){n&&n.eventSource&&(n.eventSource.close(),n.eventSource=null,delete n.eventSource),r.ajaxKill(n)}},foreverFrame:{name:"foreverFrame",timeOut:3e3,start:function(f,e,o){var h=this,l=r.foreverFrame.count+=1,c,a,s=n("<iframe data-signalr-connection-id='"+f.id+"' style='position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;'></iframe>");if(t.EventSource){o&&o();return}n(f).trigger(i.onSending),c=r.getUrl(f,this.name),c+="&frameId="+l,s.prop("src",c),r.foreverFrame.connections[l]=f,s.bind("readystatechange",function(){n.inArray(this.readyState,["loaded","complete"])>=0&&(u("Forever frame iframe readyState changed to "+this.readyState+", reconnecting",f.logging),h.reconnect(f))}),f.frame=s[0],f.frameId=l,e&&(f.onSuccess=e),n("body").append(s),a=t.setTimeout(function(){f.onSuccess&&(h.stop(f),o&&o())},h.timeOut)},reconnect:function(n){var i=this;t.setTimeout(function(){var u=n.frame,t=r.getUrl(n,i.name,!0)+"&frameId="+n.frameId;u.src=t},n.reconnectDelay)},send:function(n,t){r.ajaxSend(n,t)},receive:r.processMessages,stop:function(t){t.frame&&(t.frame.stop?t.frame.stop():t.frame.document&&t.frame.document.execCommand&&t.frame.document.execCommand("Stop"),n(t.frame).remove(),delete r.foreverFrame.connections[t.frameId],t.frame=null,t.frameId=null,delete t.frame,delete t.frameId),r.ajaxKill(t)},getConnection:function(n){return r.foreverFrame.connections[n]},started:function(t){t.onSuccess?(t.onSuccess(),t.onSuccess=null,delete t.onSuccess):n(t).trigger(i.onReconnect)}},longPolling:{name:"longPolling",reconnectDelay:3e3,start:function(u,f){var o=this;u.pollXhr&&u.stop(),u.messageId=null,t.setTimeout(function(){(function e(f,s){n(f).trigger(i.onSending);var a=f.messageId,l=a===null,v=r.getUrl(f,o.name,!l,s),c=null,h=!1;f.pollXhr=n.ajax({url:v,global:!1,type:"GET",dataType:u.ajaxDataType,success:function(u){var c=0,o=!1;s===!0&&h===!1&&(n(f).trigger(i.onReconnect),h=!0),r.processMessages(f,u),u&&u.TransportData&&n.type(u.TransportData.LongPollDelay)==="number"&&(c=u.TransportData.LongPollDelay),u&&u.TimedOut&&(o=u.TimedOut),c>0?t.setTimeout(function(){e(f,o)},c):e(f,o)},error:function(r,o){o!=="abort"&&(c&&clearTimeout(c),n(f).trigger(i.onError,[r]),t.setTimeout(function(){e(f,!0)},u.reconnectDelay))}}),s===!0&&(c=t.setTimeout(function(){h===!1&&(n(f).trigger(i.onReconnect),h=!0)},o.reconnectDelay))})(u),t.setTimeout(f,150)},250)},send:function(n,t){r.ajaxSend(n,t)},stop:function(n){n.pollXhr&&(n.pollXhr.abort(),n.pollXhr=null,delete n.pollXhr),r.ajaxKill(n)}}},f.noConflict=function(){return n.connection===f&&(n.connection=e),f},n.connection&&(e=n.connection),n.connection=n.signalR=f})(window.jQuery,window)
Please sign in to comment.
Something went wrong with that request. Please try again.