SignalR .NET client not firing events when network connection is lost - asp.net

I have WPF application that connects to WebAPI, which runs SignalR. Everything works fine, until Internet connection is lost by client.
When it happens, SignalR does not fire any events on client side (StateChanged, Error, Reconnecting, Closed etc.)
Code is pretty straightforward
public HubConnection _hubConnection;
IHubProxy _proxy;
public async Task ConnectToHub(string hubUrl, string hubName)
{
_hubConnection = new HubConnection(HubURL);
_hubConnection.Reconnecting += hubConnection_Reconnecting;
_hubConnection.Closed += _hubConnection_Closed;
_hubConnection.StateChanged += _hubConnection_StateChanged;
proxy = hubConnection.CreateHubProxy(hubName);
await _hubConnection.Start();
}
void _hubConnection_StateChanged(Microsoft.AspNet.SignalR.Client.StateChange obj)
{
throw new NotImplementedException();
}
void _hubConnection_Closed()
{
throw new NotImplementedException();
}
void _hubConnection_Reconnectig()
{
throw new NotImplementedException();
}
SignalR version 2.2.0
Thanks for help

Try subscribing to the Error event. Depending on "how" the connection is lost, I don't think some of the other events will get fired.
_hubConnection.Error += (e=>{ ... });

Transport type on SignalR was set automatically to ServerSentEvents instead of WebSockets (Server admin didn't turn it on). Turned out that only with Websockets we can get connection-related events on .Net-client, when connection is lost.
According to http://www.asp.net/signalr/overview/getting-started/introduction-to-signalr
WebSocket is the only transport that establishes a true persistent, two-way connection between client and server.

Related

Signalr core client - call server methode from Razor component

How can I send a message to my server from, let's say a Razor component?
The situation:
I have a working SignalR (Core) connection with my server.
My client code:
public class StartMySignalR
{
HubConnection connection;
public async void StartSignalRHub()
{
connection = new HubConnectionBuilder()
.WithUrl(new Uri("https://myurl.my/LogOnHub"))
.WithAutomaticReconnect()
.Build();
connection.On<string>("ReceiveMessage", (message) =>
{
//Do some stuff
ii.InsertIntoLog("INFO", "SignalR ID = " + message);
});
//Start SignalR client
await connection.StartAsync();
//Send message to server (test connection).
await connection.InvokeAsync("WelcomeMessage", connection.ConnectionId);
I send a test message to my server, that works fine. I can also send a message back from my server,.. so far so good. But now I want to do that from a Razor component in my OnInitializedAsync() Task. So when my page loads, the test message is sent to my server. There I am stuck. When I try to send the message from my Razor component I receive an error (System.NullReferenceExeption - Object reference not set to an instance of an object) -> connection was null error.
Can somebody put me in the right direction?
When I set the Hubconnection to static it works.
public static HubConnection connection;

Java gRPC: exception from client to server

Is it's possible to throw an exception from the client to the server?
We have an open stream from the server to the client:
rpc addStream(Request) returns (stream StreamMessage) {}
When i try something like this:
throw Status.INTERNAL.withDescription(e.getMessage()).withCause(e.getCause()).asRuntimeException();
I got the exception in the StreamObserver.onError on the client, but there is no exception on the server-side.
Servers can respond with a "status" that the stub API exposes as a StatusRuntimeException. Clients, however, can only "cancel" the RPC. Servers will not know the source of the cancellation; it could be because the client cancelled or maybe the TCP connection broke.
In a client-streaming or bidi-streaming call, the client can cancel by calling observer.onError() (without ever calling onCompleted()). However, if the client called onCompleted() or the RPC has a unary request, then you need to use ClientCallStreamObserver or Context:
stub.someRpc(request, new ClientResponseObserver<Request, Response>() {
private ClientCallStreamObserver<Request> requestStream;
#Override public void beforeStart(ClientCallStreamObserver<Request> requestStream) {
this.requestStream = requestStream;
}
...
});
// And then where you want to cancel
// RequestStream is non-thread-safe. For unary requests, wait until
// stub.someRpc() returns, since it uses the stream internally.
// The string is not sent to the server. It is just "echoed"
// back to the client's `onError()` to make clear that the
// cancellation was locally caused.
requestStream.cancel("some message for yourself", null);
// For thread-safe cancellation (e.g., for client-streaming)
CancellableContext ctx = Context.current().withCancellation();
StreamObserver requestObserver = ctx.call(() ->
stub.someRpc(new StreamObserver<Response>() {
#Override public void onCompleted() {
// The ctx must be closed when done, to avoid leaks
ctx.cancel(null);
}
#Override public void onError() {
ctx.cancel(null);
}
}));
// The place you want to cancel
ctx.cancel(ex);

SignalR .Net Client can't establish conection (404 not found)

I have a solution in which i am using SignalR. There is a Hub in one of the projects and SignalR.Client in the others that are connecting to that Hub.
This solution is hosted on two servers, and I have a strange problem. In one server everything works fine, but in the other i get an 404 not found error when I am trying to establish the connection from the SignalR.Client.
Hub Code:
public class GlobalHub : Hub
{
public void Hello()
{
Clients.All.hello();
}
public void Notify(string user,NotificationViewModel model)
{
Clients.Group(user).notify(model);
}
public override System.Threading.Tasks.Task OnConnected()
{
string name = Env.UserId().ToString();
Groups.Add(Context.ConnectionId, name);
return base.OnConnected();
}
}
Global.asax Hub Map:
var hubConfiguration = new HubConfiguration
{
EnableDetailedErrors = true,
EnableJavaScriptProxies = true
};
RouteTable.Routes.MapHubs("/signalr",hubConfiguration);
The connection attempt:
string portal = CommonHelper.GetPortalUrl("user");
if(portal.Contains(":50150"))
{
portal = portal.Replace(":50150", "");
}
var connection = new HubConnection(portal+"signalr",false);
IHubProxy myHub = connection.CreateHubProxy("GlobalHub");
connection.Start().Wait();
myHub.Invoke("Notify", userID.ToString(), result2);
I am pretty sure that my connection url is correct, I checked it 50 times.
Error occurs on this line:
onnection.Start().Wait();
SS of Error:
Thanks
The problem may be that when hosting a SignalR project on two servers, clients connected to one can only be connected to other clients connected to the same server. That is because SignalR doesn't automatically broadcast a message through all servers.
http://www.asp.net/signalr/overview/performance/scaleout-in-signalr
Try have a look here and I hope it is helpful to you. One of the proposed solution is to use the Redis Pub/Sub (http://redis.io/topics/pubsub) solution, or Azure Service Bus (http://azure.microsoft.com/en-us/services/service-bus/) - both of whom are use as a backplane (when a server receives a message, it is broadcast to all of them and the one that needs it can use it).
Thanks I solved the problem. It turned out that it was a problem with the server. The server itself couldnt recognize that url (throws 404 on the url).
After that problem was fixed, SignalR started working

SignalR Long Running Process

I have setup a SignalR hub which has the following method:
public void SomeFunction(int SomeID)
{
try
{
Thread.Sleep(600000);
Clients.Caller.sendComplete("Complete");
}
catch (Exception ex)
{
// Exception Handling
}
finally
{
// Some Actions
}
m_Logger.Trace("*****Trying To Exit*****");
}
The issue I am having is that SignalR initiates and defaults to Server Sent Events and then hangs. Even though the function/method exits minutes later (10 minutes) the method is initiated again ( > 3 minutes) even when the sendComplete and hub.stop() methods are initiated/called on the client prior. Should the user stay on the page the initial "/send?" request stays open indefinitely. Any assistance is greatly appreciated.
To avoid blocking the method for so long, you could use a Taskand call the client method asynchronously.
public void SomeFunction(Int32 id)
{
var connectionId = this.Context.ConnectionId;
Task.Delay(600000).ContinueWith(t =>
{
var message = String.Format("The operation has completed. The ID was: {0}.", id);
var context = GlobalHost.ConnectionManager.GetHubContext<SomeHub>();
context.Clients.Client(connectionId).SendComplete(message);
});
}
Hubs are created when request arrives and destroyed after response is sent down the wire, so in the continuation task, you need to create a new context for yourself to be able to work with a client by their connection identifier, since the original hub instance will no longer be around to provide you with the Clients method.
Also note that you can leverage the nicer syntax that uses async and await keywords for describing asynchronous program flow. See examples at The ASP.NET Site's SignalR Hubs API Guide.

SignalR Silverlight Client keeps "connected", when Hub is disconnected

I have implemented SignalR in my Silverlight 5 application and it's working fine as long as the client stays on-line. But as soon as the network connection drops for more than about 5 seconds, it stops functioning and I can't make it reconnect.
When a client loses the network connection, the Hub's event "OnDisconnected" is triggered.
But on the client side the HubConnection's Closed or StateChanged events are not triggered and the ConnectionState remains Connected. It then tries to make a call to hubproxy.Invoke(), but that will not invoke the client-side method as it would if the network connection stayed alive.
I instantiate the signalr client in App.xaml.xs:
private void Application_UserLoaded(LoadUserOperation operation)
{
//Some checks whether user is logged in
_signalRClient = new SignalRClient();
_signalRClient.RunAsync();
}
.
public class SignalRClient
{
public async void RunAsync()
{
SetHubConnection();
SetHubProxy();
await StartHubConnection();
SendTestSignal();
}
private void SetHubConnection()
{
try
{
_hubConnection = new HubConnection("https://10.1.2.3/HubWeb");
}
catch (WebException ex)
{
LoggerManager.WriteLog(LogType.ERROR, ex.ToString());
}
_hubConnection.Closed += () => TimeoutHelper.SetTimeout(5000, () => _hubConnection.Start());
_hubConnection.StateChanged += (change) => LoggerManager.WriteLog(LogType.DEBUG, String.Format("SignalR Client: Connection State Changed from {0} to {1}", change.OldState, change.NewState));
}
I tried to implement automatic reconnect, as the documentation suggests, by handling the client side Closed event and that starting the hubconnection.
But because the ConnectionState is still "Connected", this event is not triggered and I do not see a way to restart the connection from the client.
What could be the cause of the Connectionstate property of client's hubconnection not changing tot "Disconnected" and why is the Closed event not triggered?
Any help appreciated.

Resources