Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use SignalR to notify web clients from ASP.NET MVC 3 that MSMQ tasks were completed

How would one use SignalR to implement notifications in an .NET 4.0 system that consists of an ASP.NET MVC 3 application (which uses forms authentication), SQL Server 2008 database and an MSMQ WCF service (hosted in WAS) to process data? The runtime environment consists of IIS 7.5 running on Windows Server 2008 R2 Standard Edition.

I have only played with the samples and do not have extensive knowledge of SignalR.

Here is some background

The web application accepts data from the user and adds it to a table. It then calls an one way operation (with the database key) of the WCF service to process the data (a task). The web application returns to a page telling the user the data was submitted and they will be notified when processing is done. The user can look at an "index" page an see which tasks are completed, failed or are in progress. They can continue to submit more tasks (which is independent of previous data). They can close their browser and come back later.

The MSMQ based WCF service reads the record from the database and processes the data. This may take anything from milliseconds to several minutes. When its done processing the data, the record is updated with the corresponding status (error or fail) and results.

Most of the time, the WCF service is not performing any processing, however when it does, users generally want to know when its done as soon as possible. The user will still use other parts of the web application even if they don't have data to be processed by the WCF Service.

This is what I have done

In the primary navigation bar, I have an indicator (similar to Facebook or Google+) for the user to notify them when the status of tasks has changed. When they click on it, they get a summary of what was done and can then view the results if they wish to.

Using jQuery, I poll the server for changes. The controller action checks to see if there is any processes that were modified (completed or failed) and return them otherwise waits a couple of seconds and check again without returning to the client. In order to avoid a time out on the client, it will return after 30 seconds if there was no changes. The jQuery script waits a while and tries again.

The problems

Performance degrades with every user that views a page. There is no need for them to do anything in particular. We've noticed that memory usage of Firefox 7+ and Safari increases over time.

Using SignalR

I'm hoping that switching to SignalR can reduce polling and thus reduce resource requirements especially if nothing has changed task wise in the database. I have trouble getting the WCF service to notify clients that its done with processing a task given the fact that it uses forms based authentication.

By asking this question, I hope someone will give me better insight how they will redesign my notification scheme using SignalR, if at all.

like image 493
bloudraak Avatar asked Nov 17 '11 22:11

bloudraak


People also ask

What is SignalR in ASP NET MVC?

ASP.NET SignalR is a library for ASP.NET developers to add real-time web functionality to their applications. Real-time web functionality is the ability to have server-side code push content to the connected clients as it happens, in real-time.

What can SignalR be used for?

SignalR can be used to add any sort of "real-time" web functionality to your ASP.NET application. While chat is often used as an example, you can do a whole lot more. Any time a user refreshes a web page to see new data, or the page implements long polling to retrieve new data, it is a candidate for using SignalR.

Is SignalR peer to peer?

You can configure the Telerik UI Chat component for ASP.NET MVC and a SignalR 2 service to create a Peer-to-Peer Chat application. To create the Peer-to-Peer Chat, you have to implement the SignalR Hub server and then to implement the application client: Create the new application.


1 Answers

If I understand correctly, you need a way of associating a task to a given user/client so that you can tell the client when their task has completed.

SignalR API documentation tells me you can call JS methods for specific clients based on the client id (https://github.com/SignalR/SignalR/wiki/SignalR-Client). In theory you could do something like:

  1. Store the client id used by SignalR as part of the task metadata:
  2. Queue the task as normal.
  3. When the task is processed and de-queued:
    • Update your database with the status.
    • Using the client id stored as part of that task, use SignalR to send that client a notification:

You should be able to retrieve the connection that your client is using and send them a message:

string clientId = processedMessage.ClientId //Stored when you originally queued it.
IConnection connection = Connection.GetConnection<ProcessNotificationsConnection>();
connection.Send(clientId, "Your data was processed");

This assumes you mapped this connection and the client used that connection to start the data processing request in the first place. Your "primary navigation bar" has the JS that started the connection to the ProcessNotificationsConnection endpoint you mapped earlier.

EDIT: From https://github.com/SignalR/SignalR/wiki/Hubs

public class MyHub : Hub
{
     public void Send(string data)
     {
     // Invoke a method on the calling client
     Caller.addMessage(data);

     // Similar to above, the more verbose way
     Clients[Context.ClientId].addMessage(data);

     // Invoke addMessage on all clients in group foo
     Clients["foo"].addMessage(data);
     }
}
like image 147
PabloC Avatar answered Sep 27 '22 23:09

PabloC