I am relatively new to SignalR, What I have done so far are example chat applications on it to get started.
We have a project that includes multiple databases, it's a machine data collection app. I have created a web control in ASP.NET MVC to view data of multiple machines at one place.
We have multiple users and they can access machines related to their projects. The current solution have a jQuery observer on the mvc page which refreshes the machine controls in a specific time.
I am thinking of making it a Push Notification solution. But as I am a beginner on SignalR I don't know how to approach this.
The goal is to notify the user of changes in data for machines that the user has access to (Not all machines).
Also how can I send messages from a database server to SignalR notifying of changes in the data?
I need some guidance getting started on this.
SignalR Send method allows you to send data to user! It may use push, frame, server events or websocket techniques. You developer don't care about the technique! It depends on server and client handshake.
What you really need is to retrieve data from your databases and then to users, without worries
// Server side:
protected override Task OnConnected(IRequest request,
string connectionId)
{
var db = new allEntities();
var db2 =new allEntities2();
var data1 = db.Tables.Where(e=>e.LastUpdate<=datetime.now.AddDays(-1));
var data2=db2.Tables.Where(e=>e.Something==someRef);
var data=combine(data1,data2);//combine logic goes here
return Connection.Send(connectionId, data.ToList());
}
Related
Want to create one back-end for location sharing between clients and back-end should be in .net-core and MS-SQL.
Simple approach is user1 send x and y co-ordinates and save to db every 2 second and user2 call the get api and get the x and y co-ordinates in every 2 second.
Issue - If 1 million user register then 1 million request per 2 sec will hit. Not good for servers and MS-SQL
Question - Is it possible to create web socket for every user which send their location and send the data to that socket in every 2 sec and when other user who want to see the location, merge that user with socket.
or any other approach???
You can use memory based database (Redis for example) to store the data (save and answer).
Web socket as transport, but even using web sockets you need to store the data somethere. To store in the application - not a good idea.
Maybe you can use SignalR - receive data from one client and send it to all connected clients. But there will be some difficulties with many connections.
You could use Asp.net SignalR, it can send messages to all connected clients simultaneously. For example, a chat room. Or, send messages to specific clients or groups of clients.
The SignalR Hubs API provides the following method to send messages to clients:
SendMessage sends a message to all connected clients, using Clients.All.
SendMessageToCaller sends a message back to the caller, using Clients.Caller.
SendMessageToGroups sends a message to all clients in the SignalR Users group.
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
public Task SendMessageToCaller(string user, string message)
{
return Clients.Caller.SendAsync("ReceiveMessage", user, message);
}
public Task SendMessageToGroup(string user, string message)
{
return Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
}
More details information about using it, check the following links:
Tutorial: Get started with ASP.NET Core SignalR
How can I make one to one chat system in Asp.Net.Core Mvc Signalr?.
Mapping SignalR Users to Connections
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/ .
I will be deploying my first application based on WCF and would like to know the best way to deploy. Here is my architecture. Please see the attached image.
We have a WCF written using 4.0 framework and has 3 methods. A front end ASP.NET website (www.site.com) calls the WCF to save data as well as read data. In figure method1 is saving to data and method2 and 3 are for reading the data from SQL server 2008 R2 database.
In my ASP.Net webstie...
I am calling the Method1 and closing the connection...like this..
ServiceClient client = new ServiceClient();
client.Method1(data to be saved)
client.close();
I am calling method 2 and 3 as follows
ServiceClient client = new ServiceClient();
dropDown1list.datasource = client.Method2()
dropDown2list.datasource = client.Method3()
client.close();
Multiple users could be using the website at the same time to submit the data. Considering this architecture..what would be the best way to deploy the WCF so that it could handle multiple users at same time?. I read the article http://www.codeproject.com/Articles/89858/WCF-Concurrency-Single-Multiple-and-Reentrant-and and http://www.codeproject.com/Articles/86007/ways-to-do-WCF-instance-management-Per-call-Per.
I now believe I need to have my WCF service as
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple , InstanceContextMode = InstanceContextMode.PerCall )]
public class Service : IService
{
public bool Method1(data to be saved)
{
}
public List<string> Method2()
{
}
public List<string> Method2()
{
}
}
Am I right ?. Any suggestions ?.
Just answered a similar question yesterday. Based on your description and the picture, I don't see a need to change your architecture. If you're using one of the main WCF bindings (webHttpBinding, wsHttpBinding or BasicHTTPBinding), the service you deploy should easily be able handle dozens of concurrent users, all saving and reading at the same time.
Each client request will generate its own connection and web service objects, each of which can communicate concurrently with your database, whether that request is to read data or write data. When the response is sent back to the client, your WCF service will destroy the objects and clean up the memory for you as long as you're not doing something strange.
I've spent the last two years working on WCF web services on and industrial scale. Lately I've been working on a load testing / benchmarking project that spins up hundreds of concurrent users, each of which is slamming our WCF test server with XML artifacts that get loaded into the database. We've managed to load up to 160 packages (about 110kb - each per client) per second. WCF is not perfect, but it's quick, clean and scales really well.
My experience has been that your database will be your bottleneck, not your WCF web service. If your client wants to scale this archtecture up to an Amazon size web service, then you bring in an F5 load balancer and scale it up that way.
Let's assume we have 2 Redis Server Backplanes, one as Master and the other as Slave.
Each web application is using SignalR in order to push content to the connected clients as it happens and in order to connect them to the backplane I am using in Application_Start
GlobalHost.DependencyResolver.UseRedis(host, port, "", new[] {"signalr.key"});
RouteTable.Routes.MapHubs();
Now in case Master Redis Backplane fails, I would like to promote the Slave Redis server to Master and switch all existing connections from web servers to the new Master Redis Server.
In order to promote the Slave Server to Master I am using the following code
using (var conn = new RedisConnection(host, port, allowAdmin: true))
{
if (conn.ServerType != ServerType.Master)
{
conn.Open();
var makeMaster = conn.Server.MakeMaster();
var info = conn.Wait(conn.GetInfo());
conn.Wait(makeMaster);
}
}
that seems to do the work.
Can you please help me on how I can inform my web application that the backplane has changed how to connect to the new one, in order to sustain communication between my connected clients?
We don't use SignalR specifically, but we have something pretty similar in the way we use redis, especially when switching between nodes. Specifically, we use redis pub/sub to subscribe to a channel, and we broadcast to that channel when changing master.
Our configuration is a little different, because we use the delimited configuration version based around ConnectionUtils.Connect(...). This means we can specify multiple nodes, with ConnectionUtils handling the concerns of figuring out which is the current master. But in your case you could perhaps publish the new master information as part of the pub/sub. I should also note that much of the code to handle switching masters (with notification) is wrapped up behind ConnectionUtils.SwitchMaster. This includes a broadcast of the change, which you can subscribe to via ConnectionUtils.SubscribeToMasterSwitch. As a minor implementation detail, the channel it uses for this is "__Booksleeve_MasterChanged" - but that is opaque if you just use the public methods.
I am designing a webservice interface for use between a Windows CE device and a PC. The Windows CE device is server and the PC is client.
I have decided to use the gSOAP library to implement the server and I am using .NET/C# for the client. I have followed the approach described here and everything is working well.
My question is about how to best implement an asynchronous callback/event from the server to the client. I can think of two methods:
Continuously polling the server for active events
A blocking method that keeps the connection open until an event occurs
I have currently chosen option 2 and it seems to be working well. I use an asynchronous method in the client and therefore get a callback when the method completes, i.e. when an event occurs on the Windows CE device. I then immediately call the same method again so it is ready for the next event.
Example server method (no error handling):
int ns__WaitForEvent(struct soap* soap, int *eventId)
{
WaitForSingleObject(hMyServerEvent, INFINITE);
*eventId = GetCurrentEventId();
return SOAP_OK;
}
Example client (no error handling):
private void SubscribeToServerEvents()
{
var server = new MyMethods.ServicePortTypeClient(
new BasicHttpBinding(),
new EndpointAddress(myIpAddress));
AsyncCallback cb = this.Callback;
server.BeginWaitForEvent(cb, server);
}
private void Callback(IAsyncResult ar)
{
var server = (MyMethods.ServicePortType)ar.AsyncState;
var result = server.EndWaitForEvent(ar);
// Do stuff with result
}
The server must be multi-threaded for this approach to work, and the number of clients should be limited so the server does not have a large number of threads hanging with blocking methods. In my case none of these issues are a problem - it is simple to setup a multi-threaded server using gSOAP and there will only ever be one client (which I control) attached to each server.
Are there any significant disadvantages to this approach? Can you suggest a better solution?
I suggest to turn the WinCE device into a webclient instead of a webserver and the PC into a server, that will be notified on something happens on the client. It is more natural this approach, you can still use gSoap for a soap client. On the PC you should have a web-server like Apache or IIS installed, or you could make a Windows server that will host an embedded light webserver.