Executing a long-running process from a web page (2014 Redux)

Just 10 short months ago, I wrote a blog post about how to kick off a long-running process from a web page. It used jQuery to talk to an ASMX web service, and polled for the status every second.

Since then, I’ve learned a lot of new things. So, I took a look at that project and went to see how I would approach this now, with newer technologies.

DOWNLOAD: you can view or clone the VS2013 source code to this solution, with 3 web projects and a class library from this GitHub repository

OPTION 1 – The Original – jQuery + ASMX (SederSoftware.Worker.WebUI):
Just to recap, this first approach I initially did was inspired from work. I was working with a developer and we were limited on what technologies we could use for that project. So, the sample lets you kick off a long-running process in another thread and that process reports back status. jQuery on the client-side would poll once-per-second to get the latest status.

Why is this bad?

Well, it’s not bad, but it could be much better. It’s not ideal because the client-side is only getting updates when polling. This is inefficient and plus the UI only updates once per second. It would be better for the server to simply tell us when there is an update.

Also, ASMX services are limited. It’s much simpler to use WebAPI or SignalR for the backend nowadays.

OPTION 2 – SignalR (SederSoftware.Worker.WebUISignalR):
The next approach was to create a simple MVC project. In there, a single view would reach out to a SignalR service to kick off the process – and then wire up an event handler for when the server is to report back status.

If you are not familiar, SignalR is a pretty amazing component. It figures out the best form of communication between the client and the server. if you are using a modern browser though, chances are you’re connecting to a websocket for updates, which is very efficient.

Another obvious difference is there is far less JavaScript. In the Original, above, that was handling the actual AJAX calls – which required quite a bit of code. Instead, with SignalR, it’s less code and that code you do have is simply wiring up SignalR and updating the UI:

image

This approach gives a MUCH better user experience with immediately and smooth updates, and requires less-code. One gotcha to getting SignalR working is two things:

Thing 1) In App_Start, create a Startup.cs file that looks like this:

image

Thing 2) In your PropertiesAssemblyInfo.cs file, add an entry like this:

image

This are both needed to get SignalR working – and that wasn’t obvious to find, so I thought I’d write it down!

OPTION 3 – SignalR + AngularJS (SederSoftware.Worker.WebUIAngularSignalR):
Now that we have SIgnalR working, what about adding an AngularJS front-end to it. How DO you have AngularJS interact with SignalR? Well, first a best-practice is to create a “service” in Angular, that is a module that you can use from controllers. The tricky part though which stopped me dead-in-my-tracks was: “How do I publish the event I receive from the server, to my consumer?”. I wasn’t even sure how I wanted that to work, never mind how to implement it.

When I googled it on bing, I found that there was a LOT of bad AngularJS code out there. Most people don’t create services, they just put all their code in their controllers or worse, write many lines of complexticated JavaScript to achieve their goal. I definitely didn’t want to go down that path. I ended up finding an article (I can’t re-find it now, sorry I can’t cite it) – where they showed this concept of publishing the event using $rootScope, a service everyone can access. For example, here is my SignalRService:

image

In other words, any Angular controller who uses this service can start the long-running process by binding to “startProcess”. Then, that controller can receive the updates by using $on like this:

image

OK, it’s not a lot of code, but it can be a little confusing if you are not familiar with Angular. Why did we go through all of this? Well first, I’m working on a project at work that requires this, so I thought I’d figure it out. Also, the UI is even cleaner than before – this is the HTML for this process:

image

One more REALLY cool benefit of using Angular like this? Since all of the routing is done client-side, I can click on other links in my site – and when I come back to the “page” with the long-running task, it is still in the same state – showing me status, and updating! I thought that was pretty cool.

Bottom Line:
The point of all of this is simply to document some options. Here was have 3 different ways to kick off a long-running process on the web server and show rich feedback as to the status. Again, you can view the source of each of these or pull down the source from this sample repository. Let me know if you have any questions or have any ideas of better ways to do this.

Posted in ASP.NET, ASP.NET MVC, Best-practices, Computers and Internet, General, JQuery, Uncategorized, Web Services
4 comments on “Executing a long-running process from a web page (2014 Redux)
  1. […] 2014 UPDATE: See this follow-up post, which explains newer ways to do this, including using SignalR and making the UI code easier with […]

    Like

  2. Eddie Chew says:

    Hi Rob,

    Great articles!
    For Option 2, how would you implement task cancellation?

    Regards,
    Ed

    Like

    • Robert Seder says:

      Thanks! If you were using a Task, then you could return that from the long-running process – and then tie in the SignalR interface with that. It would be a few notches more complicated than this “simple” example. It might make the code significantly more confusing to add-in, but that’s the general approach I would take.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives
Categories

Enter your email address to follow this blog and receive notifications of new posts by email.

Join 4 other followers

%d bloggers like this: