long running tasks under asmx service hosted on IIS - c#

I have some legacy ASMX IIS hosted service. Client applications make subscribe or unsubscribe to the web service. Via some internal to the web service logic it needs to send messages to the subscribed applications periodically.
What is the best way to do the part of the long running task ? I understand opening Thread with long running task not a good idea to do under IIS.

ASMX services cannot do what you're asking for: they cannot just decide to send a message to the client. All they can do is respond if the client requests it.
You can hack around and come up with one method to start the long-running task, and another method to poll for the status of the task. This works, but it can be expensive.
The better model is to perform the long-running task in a separate Windows Service. Have that service host a simple WCF service which will only be used by the main service (the one that talks to the clients). The main (WCF) service would use a Duplex channel to communicate with the clients. That way, it can "call" the clients whenever there is news about one of the long-running tasks.

Usually in such cases when you don't have a way to push the result back, create an unique ID for the long running task and sent it back to the client, after that run the task and have a table in database or something else where you store the status of the task. The client will pull periodically the service to see the task' status by given ID. Once it finds the task is completed it will retrieve the result.
And is completely fine to have a thread running inside IIS doing its job.

Related

ASP.NET CQRS and long running tasks hosted in external process

I have a web application where users can enqueue tasks to export some data. The process can take up to 2-3 hours but can complete in seconds depending what was requested.
The export process will be handled like that:
public class ExportCommandHandler: IAsyncRequestHandler<ExportCommand, bool>
{
...
public async Task<bool> Handle(ExportCommand message)
{
return await _externalScheduler.EnqueueJobAsync(new ExportJob(...));
}
}
The _externalScheduler.EnqueueJobAsync currently just calls a self-hosted webapi method exposed in the external process to start a job there.
The problem here I want to get a notification when the job was completed to notify user it's ready if he's still browsing our web-site (planning to use SignalR here). If it wasn't hosted in the external process it would be obvious.
But what's the best approach to get notified when it's hosted in the external process? Is exposing a web-method in the web application for external process to call after completion is a proper way?
We're currently planning using Quartz.NET for processing external jobs but don't mind trying some other things like Hangfire.
Sorry it wasn't clear to me if the external process is owned by a third party system or it's yours.
In case it is a third party a web hook is a good and simple solution. You can define an endpoint which is called when the external process finishes.
Otherwise I would suggest using a messaging system to communicate both services. Just send a message to the external process to initiate the export, and send another message from the external process when the job is finished. This way you ensure that if one service is down at the moment of the notification the message will be sent and processed as soon as the service goes up again.

Creating MVC webservice with no timeout

I need to create a ASP.NET API service that when called doesnt wait for a response from the webserver. Basically I have a long sql task that I want to run then when its completed send an email to the user to tell them the job is done. It needs to avoid server response timeout, so something that just lets the user carry on without waiting round. I cant seem to find a way in MVC to do this, is it possible?
IMHO, I would queue this job and process it using another process outside IIS.
For example, this would be the flow:
User performs a request to your API to start the long task, but what API does in the server-side is queueing the whole task.
API returns a 200 OK response specifying that the job was queued successfully. You may use Azure Service Bus, Queues, MSMQ, RabbitMQ, Redis or even SQL Server using a table to maintain job state.
Some Windows Service, Azure Worker Role or a periodic scheduled task dequeues the task, processes it and as soon as it ends, it sends an email to the user to notify that the operation was done.
Queue the task and return the response immediately.
Basically, your server-side handler (controller action, Web API method, whatever) shouldn't invoke the long-running back-end task directly. It should do something relatively fast to just queue the task and then immediately return some indication that the task has been successfully queued. Another process entirely should actually execute the long-running task.
What I would recommend is two server-side applications. One is the web application, the other is either a Windows Service or a periodically scheduled Console Application. The web application would write a record to a database table to "queue" the process. This could contain simply:
User who queued the process
When it was queued
What process was queued (if there would ever be more than one, for example)
Status of the process ("queued" initially)
Anything else you might want to store.
Just insert a record here and then return to the user. At this point the web application has done its job.
The Windows Service (or Console Application) would check this database table for "queued" records. When it finds one, update the status to "processing" (so other executions don't try to run the same one) and invoke the long-running process. When the long-running process is complete, update the status to "complete" (or just delete the record if you don't want it anymore) and notify the user. (Handle error conditions accordingly, of course. Maybe re-try, maybe notify the user of the error, etc.)
By separating the concerns like this you place the appropriate responsibilities in the appropriate application contexts and provide the user with exactly the experience they're looking for. You additionally open the door for future functionality, such as queueing the process by means other than the web application or running reports on queued/running/failed/etc. processes by examining that database table.
Long story short: Don't try to hack a web application so that it doesn't behave like a web application. Use the technologies for their appropriate purposes.

What is the correct way to handle long running service operations with WCF hosted in IIS?

I am building a WCF service that will expose several operations, it will run in IIS because it needs HTTPS endpoints. Most of the operations will perform within seconds or less; however, one or two of these operations will take between 5-90 minutes.
The primary consumer of this service will be an ASP.NET MVC application; what is the correct way to do handle this?
Should I jackup the timeout and do some ajax calls? Should I add a table to my database, and have the long running operations update this database, and have the web interface poll this table every minute? I'm not sure what (if there is) the generally accepted best practice for this.
I wrote something similar for my senior project, basically a job scheduling framework.
I chose to go down the path of storing the "status" of the "job" in the database.
I wrote a manager windows service that implemented a WCF client (proxy)
I wrote a WCF Service that implemented my "worker host".
The manager service would read the queue from the database, and hand out work to all of my "worker hosts". The reason I had windows service perform this task as opposed to just having the UI talk directly to the worker host, was because it gave an extra level of control over the whole process.
I didn't like the idea of having "the network cable unplugged" from my worker host, and never getting a status update again from this specific job. So, the windows service gives me the ability to constantly monitor the progress of the WCF worker host, and if a connection error ever occurs (or something else unexpected), I can update the status to failed. Thus, no orphaned jobs.
Take a look at this
WCF Long Running Operations
There could be other options but they are nearly the same. You can also come up with some push notifications (I assume no data is returned) as one int the following link
WCF Push

ASP.NET and background worker process

I have a web application running on ASP.NET and using SignalR I support real-time communication between the clients and the server.
I need some type of a worker process that does work in a loop and notifies the clients as needed using the SignalR connections and the web application must be able to call the worker process. (two-way communication between a worker process and the web application)
What would you recommend for communicating between the web application and the worker ?
A scenario would be:
The request comes in from the client -> I notify the worker -> the worker does his job -> calls back to the web application -> notifies the client.
or
The worker notifies -> web application, uses the SignalR to notify -> clients
Can I share instances somehow ? Can I run this worker in the same application domain inside IIS ? How might I approach this ?
Thank you !
Usually I do communication between ASP.NET and another process (a scheduled console application in most of my cases) through a database.
I.e. the ASP.NET application writes some jobs into a jobs table and the console application (which is being ran every 10 minutes or so through Windows Task Scheduler) picks up the jobs from the database table and processes them.
You could use an asynchronous IIS-hosted WCF or Web Service where the request is initiated from the client and the response is handled in the request completion callback.
Since IIS could instantiate a separate instance of your service class, this class could call the appropriate worker directly since the user won't be directly waiting on the response.

How does the WCF service interact with my winform app?

I am currently developing a C# Windows Form Application that I intend to let it interact with a server. The server will receive posting from a mobile application that I have developed and whenever a posting is received, my Windows Form Application should be notified and give me a notification. In order to do this, I intend to use WCF duplex service for it.
E.g. My mobile application sends an posting over to my server. Once my server reads and receives the new posting, the service should send a message over to my winform app to alert me that a posting is received. And the UI of the winform app should update accordingly to what I want to updated. (e.g. adding new panels)
This is basically how I wish for it to work
They way this would work is
WCF Service in running on my server
Windows Form connects to my server's WCF service using Duplex Contract
Mobile app posts to a webpage
Once the webpage receives the posting, the asp.net will invoke the WCF service
WCF duplex service receives the posting and sends the information to the winform app
My winform Application aka WCF Client updates UI with this new message received
My question is, how does step 4 proceed to step 5? To be specific, how does the service sends the information over to the winform app upon receiving the posting.
To be even more specific, once the posting is received from the webpage, the service contract is invoked and the information is sent and received by the service, how does the service make use of the call back channel to send the information over to the winform app and update the UI accordingly?
The answer to this question depends on how your WCF service is hosted and how "big" the service will eventually be (in terms of number of simultaneous clients).
The simplest scenario is a self-hosted WCF service (meaning hosted in a Windows Service or as a desktop application--not in IIS). In this case, you can use InstancePerSession mode and make your service use sessions. In this case, you'll have a 1:1 correspondence between clients and instances of your service class. When a client connects, retrieve the callback reference and store it in a static list outside of the service class. When you need to send a message to one or more clients, simply iterate over (or find the desired client in) your list and call the appropriate function on the callback contract
If you need to host your service in IIS, then the situation is trickier because you have the possibility of multiple processes hosting your service, so your list can potentially get fragmented (or blown away in the event of an app pool recycle). In this case, you'll have to use something external to your service (MSMQ, perhaps) to notify other application pool processes that a message needs to be sent.
In terms of a duplex connection, you are really just able to communicate two way over that one connection, not with all connections of the service without doing some tricky thread stuff and shutting the door on any scalability (or using something outside the service to handle to pub/sub).
One solution though that may work a lot more along the lines of what you want to do would be SignalR. It allows a single client to make a request and then you can broadcast data from that request to other clients (or target it). Take a look at its info, its sole purpose is real time communication in .NET with multiple clients.
Also another note, is that you will want to use some sort of BackgroundWorker or something for your listening thread in WinForms so that the UI is not locked while the background operations are running.

Categories

Resources