I have simple project, where I'm using signalR, When page loads, signalR scripts are loaded succefully, however right after that, call to
http://localhost:24634/signalr/signalr/connect?transport=foreverFrame&connectionId=dca2db9c-b16a-4b96-96dc-9a6b187b6d9e&connectionData=[{"name":"notifier"}]&tid=5&frameId=1
returns 500 Internal Server Error, I checked this request in fiddler, error message says
Unexpected end when deserializing object.
Here's my Hub Definitin
[HubName("notifier")]
public class PublishingNotifier: Hub
{
[HubMethodName("send")]
public void SendMessage(string message)
{
Clients.getNotification(message);
}
}
and here's my client code
$(function () {
var publishingNotifier = $.connection.notifier;
publishingNotifier.getNotification = function (message) {
// do something
};
$('input[type=submit][id*=cmsB_ChangeStatusToPublishedTop]').on('click', function (e) {
// do something else
});
$.connection.hub.start();
});
Any ideas what can be cause of this error ?
EDIT Here is Stack Trace information
[JsonSerializationException: Unexpected end when deserializing object. Line 1, position 2.]
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CheckedRead(JsonReader reader) +75
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) +48
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) +86
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IWrappedCollection wrappedList, JsonReader reader, String reference, JsonArrayContract contract) +635
Newtonsoft.Json.Serialization.<>c_DisplayClass1.<CreateAndPopulateList>b_0(IList l, Boolean isTemporaryListReference) +124
Newtonsoft.Json.Utilities.CollectionUtils.CreateAndPopulateList(Type listType, Action2 populateList) +546
1 groups, IRequest request) +140
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateAndPopulateList(JsonReader reader, String reference, JsonArrayContract contract) +101
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String reference) +62
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) +113
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueNonProperty(JsonReader reader, Type objectType, JsonContract contract, JsonConverter converter) +118
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType) +125
Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) +311
Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) +107
Newtonsoft.Json.JsonConvert.DeserializeObject(String value, JsonSerializerSettings settings) +66
SignalR.JsonNetSerializer.Parse(String json) +57
SignalR.Hubs.HubDispatcher.CreateConnection(String connectionId, IEnumerable
SignalR.PersistentConnection.ProcessRequestAsync(HostContext context) +227 SignalR.Hubs.HubDispatcher.ProcessRequestAsync(HostContext context) +120
SignalR.Hosting.AspNet.AspNetHandler.ProcessRequestAsync(HttpContextBase context) +463
SignalR.Hosting.AspNet.HttpTaskAsyncHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +68
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
EDIT2:
One more note - from the page that runs without any errors, requested url looks like this
localhost:24634/signalr/signalr/connect?transport=foreverFrame&connectionId=98e6d5b3-b164-4013-92c2-418aa6254f9e&connectionData=%5B%7B%22name%22%3A%22notifier%22%7D%5D&tid=7&frameId=1
and the failing request url looks like this
localhost:24634/signalr/signalr/connect?transport=foreverFrame&connectionId=9b398750-99d6-4188-88b5-b41ad9eb82d5&connectionData=[{"name":"notifier"}]&tid=1&frameId=1
As you may notice, the ways connectionData query string parameter is defined in urls are different, in particular, for the first url, connectionData has been url encoded the query string value, and the second query string parameter has been html encoded. I've looked into request headers, failing request Content-Type is text/html, and the second request's Content-Type: application/json.
EDIT 3:
I've found where connectionData get's parsed, in jquery.signalR-0.5.3.js file, here's code that actually encodes connectionData value
if (connection.data) {
qs += "&connectionData=" + window.escape(connection.data);
}
as you can see, window.escape() is responsible for encoding connectionData, but, if I debug this code, I can see that window.escape(connection.data) indeed html encodes connection.data instead of url encoding. But this is happening only on one page, on anothers, it works as expected.
To sum up, the problem turned out to be that window.escape
was overridden by a third party JS library. This caused window.escape
to behave differently than "normal" causing SignalR to fail as a side-effect.
So basically - when these "weird" issues occur - check if you have included libraries that "interfere" and make sure to use proper namespacing ( e.g. using the module pattern ) to avoid this issue.