Question

Background:

Here's my project: On an ASP.NET MVC4 web app, users enter information and post to the server. The server then starts running a long task (anywhere from less than a second to 20 minutes. Usually about 4 minutes.)

I don't want all of the work happening in the Controller action, or else the user would have to wait for it to complete with no feedback about what's going on. So I'd like to send the user to a status page and send updates from the server to that page.

Current Partial Solution:

Here's what I have so far: The Controller starts a Task with the long running action and then directs the user to the status page. As the task runs, it sends messages back to the status page with SignalR, and the page updates.

Problems:

  1. SingalR is updating all Clients, so more than one user can't use this app at the same time. I see that SignalR has a way to send messages to specific clients, but how can I get the client ID to the Controller? SignalR makes it difficult (impossible?) to access the Session.
  2. What if the Task finishes before the status page loads (or what if there's a pause between updates right as the page loads?) The status page won't have any information about the Task. Again, it would be nice to store the status the Session, but I can't seem to make that work.

Is there a way to get SignalR and ASP.NET to synchronize client state? Is SignalR the right tool for the job?

Was it helpful?

Solution 2

For Problem1, Client sends a request to start a task, MVC processes the request and should send a response containing a taskId. From the new webpage, a SignalR connection is started and you should define a Hub Method like Register(taskId) and on server map the taskId to Context.ConnectionId – Gustavo Armenta Aug 29 at 19:04

@GustavoArmenta Ok, so the server sends the client back some manner of ID for the task, the client then connects through SignalR and registers its TaskID, which is then mapped to the client ID. Then the running task uses that mapping to send information back, right? But how does the task access the mapping of task ID to client ID? How does a Controller access persistent data in a SignalR hub? – Danation Aug 29 at 19:15

Well, you could save the mapping on memory with a static Dictionary or persist data to a database – Gustavo Armenta Aug 30 at 16:47

@GustavoArmenta, I ended up going with your option (I was able to fix both problems.) If you add it as an answer, I will accept it. – Danation Sep 18 at 4:17

OTHER TIPS

I have made a Library for just what you need, its a wrapper library around SignalR. It requires you to have somekind of message bus / event aggregator. My library then proxies between your message bus and SignalR clients.

This way your background worker can in a easy way send progress reports both to other components of back end and to the clients seamless.

Install using nuget

Install-Package SignalR.EventAggregatorProxy

You need to implement a service bus / event aggregator. Caliburn Micro has a light footprint one

Install-Package Caliburn.Micro.EventAggregator

Follow the wiki how to set it up

https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/wiki

Once your done with setting it up you can listen to events like this from javascript

ViewModel = function() {
   signalR.eventAggregator.subscribe(MyApp.Events.BackgroundWorkerProgressEvent, this.onProgressEvent, this);
};

Forgot to mention that there is a Demo project here https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/tree/master/SignalR.EventAggregatorProxy.Demo.MVC4

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top