SignalR in SL5 stops working after upgrade to 1.0.1 - c#

I have a simple Hub that was working with 1.0.0-rc2 between my web app and my SL5 application.
After upgrading to 1.0.1, my .Net Winform clients can still connect to the hub, but my SL5 client can no longer connect.
Upon calling Subscribe, I can see the Negotiate call in Fiddler (which returns 200, with what appears to be valid JSON), followed by the hub Closed event firing. The Error event never fires, and then that's the end of it. There is no attempt to actually connect, at least as far as I can tell in Fiddler.
Any ideas? Here's my SL5 code, it's pretty simple/straight forward.
hub = new HubConnection("http://localhost/ADE");
hub.Closed += new Action(hub_Closed);
hub.Error += new Action<Exception>(hub_Error);
hub.Reconnected += new Action(hub_Reconnected);
hub.Reconnecting += new Action(hub_Reconnecting);
hub.StateChanged += new Action<StateChange>(hub_StateChanged);
hubProxy = hub.CreateHubProxy(hubName);
//Removed my hubProxy.On calls for brevity.
hub.Start().ContinueWith(task =>
// {
//});

Try this sample that is using SignalR1.0.1 and SL5.
To access SL5 client navigate to http://localhost:18628/SignalR.Sample.SilverlightClientTestPage.aspx
On Fiddler, you should get these http requests
http://localhost:18628/signalr/negotiate?noCache=cd92304d-c824-4c91-abdd-e77c8d096b58
http://localhost:18628/signalr/connect?transport=serverSentEvents&connectionToken=rse-NdoiZ1Hi7riN_beL6J-zrkGMPm1A9p8urTZn_1sTuZVeEzVWayykaN-Km_fmqBoV06D1e7h5fPWl4kgggABs3x7wiItdd8zJKE9FSCjZsYEUQOdFrzAg-WmA7rUx0&connectionData=[{"Name":"SampleHub"}]&noCache=0c4c1fa1-9aa9-409b-acf7-165faa0d699a
http://localhost:18628/signalr/send?transport=serverSentEvents&connectionToken=rse-NdoiZ1Hi7riN_beL6J-zrkGMPm1A9p8urTZn_1sTuZVeEzVWayykaN-Km_fmqBoV06D1e7h5fPWl4kgggABs3x7wiItdd8zJKE9FSCjZsYEUQOdFrzAg-WmA7rUx0

Related

SignalR disconnect doesn't fire immediately

I am trying to handle disconnect error with reconnection so I used the nextRetryDelayInMilliseconds method for reconnection, but in this case, if the connection is lost or there are some problems with the connection, the onclose handler does not work.
I am using "#microsoft/signalr": "^7.0.2" package in Angular project
I used "withAutomaticReconnect" option, but it doesn't fire immediately. I get a callback after some timeout.
Connection builder:
this.hubconnection = new HubConnectionBuilder()
.withUrl(url)
.withAutomaticReconnect({
nextRetryDelayInMilliseconds: () => {
this._errorState$.next(true);
return 1000;
}
})
.build();
Error handler (which doesn't fire if I use "withAutomaticReconnect"):
this.hubConnection.onclose(error => callback(error)
Expecting to handle the error immediately when there are some errors related to connection.
After test, I found the correct format should be like below.
connection.onclose(() => {
});
In your scenario, code should be
this.hubConnection.onclose((error) => {
console.error(`Something went wrong: ${error}`);
});
After testing, if you restart the signalr server, you may not get the error information, which should be normal. I don’t know if you can see more in the production environment. This is the standard usage, you can also refer to the following Link.
onclose event in signalr client
Suggestion:
The test above I test in signalr javascript client, and I also reproduce the issue, if it not works, please use #microsoft/signalr 7.0.0 version to troubleshoot problems caused by the new version.
I also using reconnectDelay property when build the connection.
var connection = new signalR.HubConnectionBuilder().withUrl("/mainHub")
.withAutomaticReconnect({
nextRetryDelayInMilliseconds: () => {
this._errorState$.next(true);
return 1000;
},
reconnectDelay: 500 // set the reconnect delay to 500ms
})
.configureLogging(signalR.LogLevel.Trace).build();

Simple.OData BeforeRequest event not triggered

I'm using the Simple.OData adapter to try to connect to an OData service. The service needs authentication to connect.
I have registered the BeforeRequest event to set the neccesary headers before doing any request.
However, my BeforeRequest is not triggered at all which results in not being able to open the Context, due too missing credentials and my code hangs and waits forever.
See my code below, am I missing something?
public void GetData()
{
var oDataFeed = new ODataFeed(ApiBaseUrl);
oDataFeed.BeforeRequest += BeforeRequest;
oDataFeed.AfterResponse += AfterResponse;
Context = Database.Opener.Open(ApiBaseUrl);
// do some more
}
private void BeforeRequest(HttpRequestMessage httpRequestMessage)
{
// add headers.
}
It did seem to fire or trigger the event once, however, after a rebuild of the project it doesn't work anymore.
There is a know bug in Simple.Data.Client 3x that affects request interception in certain scenarios. The bug is fixed in the forthcoming version 4 of Simple.OData.Client, currently available as pre-release but it's very stable and comes with tons of new features including support for JSON payload and OData protocol V4.

Get all events from Asterisk 12

In my application I want to show a real time overview of all active calls on a asterisk server.
That's why I want to get all events (channel created/destroyed etc.) from Asterisk 12 server using the Asterisk 12 REST API (ARI).
When I connect to the websocket I only get events that are somehow targeted to my application that I specified in the initial call to "/ari/events" (in this case "hello").
$ wscat.py 'ws://localhost:8088/ari/events?app=hello&api_key=...'
How can I get all events (e.g. also information about new incoming calls)?
Or is there another possibility to get the desired information?
I am using AsterNET.ARI .NET Stasis Framework and the following code:
// Create a message client to receive events on
Client = new ARIClient(
new StasisEndpoint(Host, Port, Username, Password),
AppName
);
Client.Connect();
Client.OnChannelStateChangeEvent += Client_OnChannelStateChangeEvent;
The method Client_OnChannelStateChangeEvent is only called for calls that I have originated by my application using Client.Channels.Originate(...).
You can use AMI(manager interface)
http://www.voip-info.org/wiki/view/Asterisk+manager+API
http://www.voip-info.org/wiki/view/asterisk+manager+events

Keep WebSocket and some event handlers alive while app is active

I use Caliburn.Micro to build a Windows 8.1 Universal app. The app connects to a web service using a WebSocket. I would like this connection, once established, to be kept alive as long as the app is active, no matter what page the user is on.
Currently I'm doing it like this:
container = new WinRTContainer();
container.Singleton<IConnectionService, ConnectionService>();
and it seems to work as I want to. I can inject it in my viewmodels and the connection is still open and it does receive messages even when a view model that does not inject the service is active. I am however a bit curious if this is the correct way (and if it's actually doing what I'm expecting)?
Secondly, I'm using the connection manager to parse the JSON returned from the WebSocket connection and creating corresponding classes like RandomThingHappened and broadcasting these using the event aggregator service from Caliburn.Micro. View interested in these can subscribe and do what they want. However, there are some messages that I would like handled regardless of which view the user is on. Is this possible? I've thought about creating singletons for this as well, and just make sure to instantiate these somewhere. That does however seem a bit... risky.
Suggestions?
Not really sure about websocket but
I am using the following ways for My WCF service ( the dumb terminal must be always connected cause the WCF service will push message to connected terminal using callback
[OperationContract(IsOneWay = true)]
void KeepConnection();
and in your client use a timer to keep calling the service
var timer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 50) };
timer.Start();
timer.Tick += (sender, args) =>
{
try
{
if (this.client.State == CommunicationState.Faulted)
{
this.RegisterTerminal();
}
this.client.KeepConnection();
}
catch
{
throw new Exception("Failed to establish connection with server");
}
};
As for the broadcasting you can use EventAggregator to publish your event to all the listening class.
you can read it more here Event Aggregator

Windows Phone 8 push notification push channel always creates new channel uri

I wanted to check that my push notification implementation is correct.
Each time I open my app (in actual fact I register the push channel only on a specific page so it's each time I go back and forth from that page) a new push channel URI is created which I store in my mobile services database to send push notifications to. This doesn't seem correct to me as each time the app/page is opened a new push channel URI is generated and so the list of channel URIs just grows and grows for each device that uses my app. I'd assume that you create a push channel, store the channel URI and push to it as needed. I will make note here that I am using raw push notifications.
I understand that push channels will expire every so often but for me it's occurring each time I back out of the app/page and therefore when onNavigateTo is called I find the push channel which does exist and a new channel URI is always created. Is this correct?
My code is as follows:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
registerPushChannel();
}
private void registerPushChannel()
{
// The name of our push channel.
string channelName = "RawSampleChannel";
// Try to find the push channel.
pushChannel = HttpNotificationChannel.Find(channelName);
// If the channel was not found, then create a new connection to the push service.
if (pushChannel == null)
{
pushChannel = new HttpNotificationChannel(channelName);
// Register for all the events before attempting to open the channel.
pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);
pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotificationReceived);
pushChannel.Open();
}
else
{
// The channel was already open, so just register for all the events.
pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);
pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotificationReceived);
// code which passes the new channel URI back to my web service
}
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
pushChannel.Close();
}
So to clarify, the app is opened and the push channel is registered and the channel uri is saved in my web service. The web service then sends notifications to the channel uri. When I exit the app or page and return to it, the push channel is found but a new channel uri is created which I again save to my web service. My channels table in effect just keeps growing and growing.
So is this the way it should work with new channel URIs continually generated? It kind of doesn't make sense to me. I'm not sure how toast and tile notifications work but I'd assume the channel URI needs to be static when the app closes to keep receiving notifications while the app is closed, but perhaps that could be a functionality of bindtotoast and bindtotile and so what I'm doing is correct because it's to do with raw notifications.
You're mostly doing it right.
Push Notifications are a funny thing.
You create a channel, send it to your server and then the server can send until it fails (the channel Uri expires or there's an error).
At which point the app needs to create a new ChannelUri and then UPDATE the value stored for that app/device on the server. The server will then be able to send notifications.
Some important points
When a new channel Uri is requested for one that is still valid you'll get the same one back.
When your ask for a new channel uri and the current one has expired, you'll normally get the same uri returned but the channel will be made live again.
There is no way to know if a channel has expired from within an app without running code like your registerPushChannel method. (Unless you track this on your backend and the app queries the backend.)
There is no way to tell the app that a channel has expired, or tell the user to reopen the app to re-establish a channel connection using the push infrastructure.
The standard way to try and ensure that the channel is always available is to check the channel whenever the app is started.
This is what you're doing, you probably just want to make sure you're updating server records not just adding more.

Categories