Multiple website server side Clients.All.receiveNotification challenge with SignalR - c#

So I have two websites that I am using SignalR and I have the following in both my Global.asax files:
HubConfiguration hubConfig = new HubConfiguration();
hubConfig.EnableCrossDomain = true;
RouteTable.Routes.MapHubs(hubConfig);
I have a server side event side and I get the hub context to send a message to all listening clients:
var signalrContext = GlobalHost.ConnectionManager.GetHubContext<Notifications.OfferHub>();
signalrContext.Clients.All.receiveNotification("hello world");
The same event happens server side on both websites and I would like to broadcast this cross-domain to all listening clients. I am thinking this is not possible server side because I will not be able to get the HubContext for both websites change the hub.url server side.
Unless anyone has any other suggestions?

Well, it took me a minute to realize what do here. Thanks to David Fowler for his help and SignalR awesomeness! I ended up adding a ServiceReference in each website to a web service in the other website and calling a "Broadcast" WebMethod. The web service webmethod just gets the current SignalR context and broadcasts my message to all clients listening on the respective website.

Related

How to disconnect SignalR form client side to achieve timeout funcitonality

I have client-side code that sends requests to server for some data. Sometime server don't respond and it take too long to establish connection. I want to set some timeout functionality on client-side so after that timeout, client will stop to try connecting server. In simple web request we can use timeout functionality. For example I am using the following code somewhere else and it is working fine for non-signalr request.
But when I send request through signalr, I can not set timeout to end this request and show user a message that data could not be fetched from server.
On this site someone suggested "Send a specific string to the client to force the disconnect" but that is not my scenario. I want to handle it on client side.
var refit = RestService.For<SomeApi>(new HttpClient
{
BaseAddress = new Uri(BASE_URL),
Timeout = TimeSpan.FromSeconds(30)
});

Publish/Subscribe Pattern in C# WCF

How to register client on server to listen some change? I want to notify my client and send some data when something changed on my server. Also, I use NetTcpBinding. I tried many examples, but I can't get method from server to register in. I don't have any config file.
Thanks in advance.
There is example of registering client on server.
ChannelFactory<ITrending> factory = new ChannelFactory<ITrending>(
new NetTcpBinding(), new EndpointAddress(#"net.tcp://localhost:6000/ITrending"));
proxy = factory.CreateChannel();
You can use the CallBack functionality in WCF services , it can be used for sending the changes in any entity or object value. In this case, Client must act as a server and server as a Client to receive the updates based on the method in the Client which is receiving the changes.
More detailed explanation : http://www.dotnetcurry.com/wcf/721/push-data-wcf-callback-service

How to send updates from server to clients?

I am building a c#/wpf project.
It's architecture is this:
A console application which will be on a virtual machine (or my home computer) that will be the server side.
A wpf application that will be the client app.
Now my problem is this - I want the server to be able to send changes to the clients. If for example I have a change for client ABC, I want the server to know how to call a service on the clients computer.
The problem is, that I don't know how the server will call the clients.
A small example in case I didn't explain it well:
The server is on computer 1, and there are two clients, on computers 2 and 3.
Client 2 has a Toyota car and client 3 has a BMW car.
The server on computer 1 wants to tell client 2 that it has a new car, an Avenger.
How do I keep track and call services on the clients?
I thought of saving their ip address (from calling ipconfig from the cmd) in the DB - but isn't that based on the WI-FI/network they are connected to?
Thanks for any help!
You could try implementing SignalR. It is a great library that uses web sockets to push data to clients.
Edit:
SignalR can help you solve your problem by allowing you to set up Hubs on your console app (server) that WPF application (clients) can connect to. When the clients start up you will register them with a specified Hub. When something changes on the server, you can push from the server Hub to the client. The client will receive the information from the server and allow you to handle it as you see fit.
Rough mockup of some code:
namepsace Server{}
public class YourHub : Hub {
public void SomeHubMethod(string userName) {
//clientMethodToCall is a method in the WPF application that
//will be called. Client needs to be registered to hub first.
Clients.User(userName).clientMethodToCall("This is a test.");
//One issue you may face is mapping client connections.
//There are a couple different ways/methodologies to do this.
//Just figure what will work best for you.
}
}
}
namespace Client{
public class HubService{
public IHubProxy CreateHubProxy(){
var hubConnection = new HubConnection("http://serverAddress:serverPort/");
IHubProxy yourHubProxy = hubConnection.CreateHubProxy("YourHub");
return yourHubProxy;
}
}
}
Then in your WPF window:
var hubService = new HubService();
var yourHubProxy = hubService.CreateHubProxy();
yourHubProxy.Start().Wait();
yourHubProxy.On("clientMethodToCall", () => DoSometingWithServerData());
You need to create some kind of subscription model for the clients to the server to handle a Publish-Subscribe channel (see http://www.enterpriseintegrationpatterns.com/patterns/messaging/PublishSubscribeChannel.html). The basic architecture is this:
Client sends a request to the messaging channel to register itself as a subscriber to a certain kind of message/event/etc.
Server sends messages to the channel to be delivered to subscribers to that message.
There are many ways to handle this. You could use some of the Azure services (like Event hub, or Topic) if you don't want to reinvent the wheel here. You could also have your server application track all of these things (updates to IP addresses, updates to subscription interest, making sure that messages don't get sent more than once; taking care of message durability [making sure messages get delivered even if the client is offline when the message gets created]).
In general, whatever solution you choose is plagued with a common problem - clients hide behind firewalls and have dynamic IP addresses. This makes it difficult (I've heard of technologies claiming to overcome this but haven't seen any in action) for a server to push to a client.
In reality, the client talks and the server listens and response. However, you can use this approach to simulate a push by;
1. polling (the client periodically asks for information)
2. long polling (the client asks for information and the server holds onto the request until information arrives or a timeout occurs)
3. sockets (the client requests server connection that is used for bi-directional communication for a period of time).
Knowing those terms, your next choice is to write your own or use a third-party service (azure, amazon, other) to deliver messages for you. I personally like long polling because it is easy to implement. In my application, I have the following setup.
A web API server on Azure with and endpoint that listens for message requests
A simple loop inside the server code that checks the database for new messages every 100ms.
A client that calls the API, handling the response.
As mentioned, there are many ways to do this. In your particular case, one way would be as follows.
Client A calls server API to listen for message
Server holds onto call, waiting for new message entry in database
Client B calls server API to post new message
Server saves message to database
Server instance from step 2 sees new message
Server returns message to Client A.
Also, the message doesn't have to be stored in a database - it just depends on your needs.
Sounds like you want to track users à la https://www.simple-talk.com/dotnet/asp.net/tracking-online-users-with-signalr/ , but in a desktop app in the sense of http://www.codeproject.com/Articles/804770/Implementing-SignalR-in-Desktop-Applications or damienbod.wordpress.com/2013/11/20/signalr-a-complete-wpf-client-using-mvvm/ .

How to use a duplex wcf service to distribute messages to all clients?

I am building a simple duplex wcf service. In this service clients send messages to the server and the server distributes the message to all connected clients. However, despite the fact that I defined the ServiceBehavior attribute as
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)], only the client who sent the message receives it back from the server, while the other clients do not. I verified that there is just one instance of the server running.
What did I do wrong? I looked at other similar questions on the web, and they all say that I should define InstanceContextMode = InstanceContextMode.Single, which I already did.
Do you have a callback Contract. So that server will reply back to client.
Check the below tutorial for Implementing Callback Contract
Click here
Also check the below Project Event Notification server. This project is doing similar things what you want.
CodeProject Link
Feel free to ask me if you need any more clarification
You need to maintain the clistList as shown in the code snippet.
List<IMessageServiceCallback> clientList = new List<IMessageServiceCallback>();
public void Register()
{
IMessageServiceCallback callback = OperationContext.Current.GetCallbackChannel<IMessageServiceCallback>();
clientList.add(callback);
}
When you want to broadcast this message. You can iterate through the list and call the callback function to send message to clients.

Using an IP address for a WCF Service

I have a C# app that calls my WCF on my server.
At some time I will want to move part of my uploading process from client to server to a different server.
So, this is what I was going to do.
My desktop application invokes a WCF hosted on my server using the full DNS name ~ www.mysite.com.
That [web method] will then return an IP address to the client.
The client will then upload images to a DIFFERENT server that is accessible only by an IP address.
The idea is that if my app is successful and I would need to 'load-balance' the image uploads I would then have a mechanism to specify different destination servers to my clients.
So, I started looking in StackOverFlow for a way to dynamically set the IP address/End-Point of my WCF. This was easy to do for web services but it seems to me a bit more difficult for WCF.
Needless to say I was about to go through the answers here but came across a comment saying that the WCF needs to be using DNS.
Is this true?
As this is the only server I got and it is using DNS (I have not got access to a secondary server yet) I cannot test this out.
Are both things possible?
When you write a web service client, you can change the server endpoint programmatically. It has nothing to do with using WCF or not in the server.
MyClient client = new MyService.MyClient();
client.Endpoint.Address = new EndpointAddress(new Uri("target URL"));
client.Open();
You could find more details on the EndPointAddress MSDN reference.
Hope I helped!
MyClient client = new MyService.MyClient();
client.Endpoint.Address = new EndpointAddress(new Uri("target URL"));
client.Open();
It works, we could also use
myService.MyClient client = new myService.MyClient ();
//enter code here, when the service is created as wcf application

Categories

Resources