Async Web Service Calls - c#

I'm looking to create a web service and accompanying web app that uses an async web service call. I've seen plenty of suggestions on how to do async calls but none seem to fit exactly what i'm trying to do or are using a really outdated tech. I'm trying to do this in ASP.net 3.5 (VS2008)
What i need to do is:
the webpage needs to submit a request to the service
the page then needs to poll the service every 5 seconds or so to see if the task has completed
once complete the request needs to be retrieved from the service.
Could someone give me some suggestions or point me in the right direction?

The way I have typically handled asynchronous server-side processing is by:
Have the webpage initiate a request against a webservice and have the service return an ID to the long-running transaction. In my case, I have used Ajax with jQuery on the client webpage and a webservice that returns data in JSON format. ASP.NET MVC is particularly well suited for this, but you can use ASP.NET to return JSON string in response to a GET, or not use JSON at all.
Have the server create a record in a database that also stores the associated data to be processed. The ID of this transaction is returned to the client webpage. The service then sends a message to a third service via a message queue. In my case, the service was a WCF service hosted in a Windows Service with MSMQ as the intermediary. It should be noted that it is better not to do the actual task processing in ASP.NET, as it is not meant for requests that are long-running. In a high demand system you could exhaust available threads.
A third service receives and responds to the queued message by reading and processing necessary data from the database. It eventually marks the database record "complete".
The client webpage polls the webservice passing the transaction record ID. The webservice queries the database based on this ID to determine if the record is marked complete or not. If it is complete, it queries for the result dataset and returns it. Otherwise it returns an empty set.
The client webpage processes the webservice response, which will either contain the resulting data or an empty set, in which it should continue polling.
This just serves as an example, you may find that you can take shortcuts and avoid doing processing in a third service and just use ASP.NET threads. But that presents it's own problems, namely how you would have another request (the polling request) know if the original request is complete. The hackish-solution to that is to use a thread-safe collection in a static variable which would hold a transaction ID/result pair. But for that effort, it really is better to use a database.
EDIT: I see now that it appears to be a demonstration rather than a production system. I still stand by my above outline for "real-world" situations, but for a demo the "hackish" solution would suffice.

Which part are going to need to do async ? As far as I can tell your actions are synchronous:
1) -> 2) -> 3)
A simple web service would do, IIS (as any web server) supports multiple request to be handled async so you have no problem.
Something which you may need to be aware of. And also the javascript engine executes code in a single thread.

Step 0: Create the web service.
Step 1: Create the web app project (assuming it's ASP.NET).
Step 2: Add a web reference to the webs service to your web app project.
Step 3: The reference would create a proxy for you, using which you can invoke both synchronous and asynchronous calls.

Related

Handling Long-Running Processes in an ASP.net Web API 2 Service

I created a REST service using ASP.net Web API 2. The service allows a client to POST records which are stored in a SQL Server database. At this point some other process needs to pull the records from the database, process them, and send the results to another, separate REST service.
Since the processing of the records will be time-consuming, I don't want to perform this step as part of the POST action, but I'm trying to figure out the best approach to designing this other process.
Is there a way to integrate this functionality into the ASP.net REST API project, or is something like a Windows Service the best solution?
You could write your web service asynchronously. So that,
public async Task<HttpResponseMessage> PostRecords(Records records)
{
await [POST data to db]
// process records asynchronously without awaiting
}
You can also perform the post operation synchronously and at the same time track the completion of the post in your database. And as you mentioned, have a job or windows service process the completed posts separately.
You can use Quartz.NET scheduling library within the asp.net mvc or web api. Define a job which executes your query and fire the job from your post action.

How do I keep a task alive after the method that called it has exited?

I'm writing a webservice that drops off a long-running bulk insert command to a sql db through a stored proc. I don't want the webservice hung up while waiting for a response from the db, so I'd like to just return an http response that lets the client know the request has been sent to the db after I start the task. But as soon as I return the response, the task will lose context and get trashed, right? How should I keep this alive?
In general, it's not a good idea to spin off something to do work from IIS. What happens if the AppPool restarts? What happens if there is an exception?
Instead, I would recommend writing a Windows Service and have it responsible for the work.
Based on your comments, I would see if you can ask for the following requirements (theoretically):
All external calls are done through the web service. The web service uses a separate assembly for the actual data access.
A separate windows service is used for long running processes, which would also use the same data access assembly the web service uses.
That is really the best way to go (but not necessarily doable based on requirements).
I think it's more of a architecture question than just about maintaining the 'context'. And talking about architecture, I think WCF webservices would help in your scenario.
What you would need is a service with callback contract. Where the service takes a request, returns an ack, stores the client context (for callback), and triggers off a long running database task in background. When the task completes, it reads client context and calls the callback handler with the result.
This article at MSDN suggests how to do a callback contract in webservice.
Hope this helps!

Using Task with ASP.NET

I am trying to get some asynchronous work done with the System.Threading.Tasks.Task class. The scenario is simple. I have a web app and in one button click event I start a Task which must run to check some outside service for a couple of minutes. It is not a heavy task. All it's going to do is send a request every 5 seconds and get a response. But it must do it for at least a couple of minutes. So, I don't want user to wait until this task gets job done. After I have started the task, I immediately return to the user saying that the task started and he/she will be informed when it is done. I wonder if this task I created will cause any problems, since I returned and ended the HTTP response.
This type of "asynchronous work" isn't possible by using the Task type. As I mention on my blog, async does not change the HTTP protocol; you still get one response per request, that's it!
The ideal ASP.NET app does not do any work outside of a request/response pair. There are ways to make it work (also described on my blog), but it's almost never recommended.
The proper solution is to split up the processing. A web site (or service) should start the processing by placing a request into persistent storage (e.g., Azure queue), a separate worker service (e.g., Azure worker role / Win32 service) would do the polling and put the results into persistent storage (e.g., Azure table), and the web site/service could poll that.
You can consider using message based service bus, and a good tutorial on MSDN Building
Distributed Apps with NHibernate and Rhino Service Bus will be
very useful.
If you just return from a standard asp.net request then wouldn't you expect the HttpResponse to end? Starting up a task in itself won't hold the HttpResponse open, to that you'd need to stream your response and block on the server until your task is finished which is presumably not what you want to do?
Maybe you should look at some ajax on the client that periodically pings the server to see if the task has finished, or at HTML 5 push notifications if you know your browser is going to support it.
You can use this http://www.asp.net/web-forms/tutorials/aspnet-45/using-asynchronous-methods-in-aspnet-45 but imho ajax with web service much better

Website Calling Windows Service With Callback

I have a WCF service hosted in a Windows Service. I want a website to be able to call it asynchronously and then when the work is finished the WCF service will let the website know the result. I've looked at various ways of achieving this but I would like to get some more advice on which way would be best. I've looked into using callbacks but also read they can be unreliable. I've read about not doing it this way at all and just having another interface in my service for the website to query the status. I've looked at using MSMQ which at the moment looks like my preferred way forward but would like some more info on how to set this up or whether I shouldn't do it this way.
Does anyone have any advice please?
The nature of any communication on a network is unreliable. The statement:
I've looked into using callbacks but also read they can be unreliable
Assuming you mean WCF callbacks, they are as unreliable as the clients/servers themselves, they all use the same mechanism.
That said, you can store the client of your WCF service in the HttpApplicationState (if the call is application-wide) or HttpSessionState (if the call is local to a session).
When generating the proxy, make sure that you check the option (or specify on the contract) that you are using asynchronous calls.
Then, you would make the call, using a callback (delegate) to indicate when the async call completed.
When the call completes, you would then store the result in the session state.
If this is something that a client on the front end needs to be aware of, then the browser will have to poll your site, checking for the return result, redirecting to a page that can display the results when the result is populated.
Selecting a binding for your application depends on
Architecture of your application
Requirements
interoperability required or not.
response time of the application
availability of time to implement
Infrastructure you are using or want to use.
As your application is a web application and is built on a request/response model, you will not be able to use asyncronous or msmq style for this architecture(or is not adviceable), because there will not be any thread listining for a delayed async response or msmq call.
you can make use of one way Methods and direct calls to methods. in this case to reduce response time you have to device ways to optimize your service methods and the processing it is doing.

How to Create a Queue

I have an application built that hits a third party company's web service in order to create an email account after a customer clicks a button. However, sometimes the web service takes longer than 1 minute to respond, which is way to long for my customers to be sitting there waiting for a response.
I need to devise a way to set up some sort of queuing service external from the web site. This way I can add the web service action to the queue and advise the customer it may take up to 2 minutes to create the account.
I'm curious of the best way to achieve this. My initial thought is to request the actions via a database table which will be checked on a regular basis by a Console app which is run via Windows Scheduled tasks.
Any issues with that method?
Is there a better method you can think of?
I would use MSMQ, it may be an older technology but it is perfect for the scenario you describe.
Create a WCF service to manage the queue and it's actions. On the service expose a method to add an action to the queue.
This way the queue is completely independent of your website.
What if you use a combination of AJAX and a Windows Service?
On the website side: When the person chooses to create an e-mail account, you add the request to a database table. If they want to wait, provide a web page that uses AJAX to check every so often (10 seconds?) whether their account has been created or not. If it's an application-style website, you could let them continue working and pop up a message once the account is created. If they don't want to wait, they close the page or browse to another and maybe get an e-mail once it's done.
On the processing side: Create a Windows service that checks the table for new requests. Once it's done with a request it has to somehow communicate back to the user, maybe by setting a status flag on the request. This is what the AJAX call would look for. You could send an e-mail at this point too.
If you use a scheduled task with a console app instead of a Windows service, you risk having multiple instances running at the same time. You would have to implement some sort of locking mechanism (at the app or request level) to prevent processing the same thing twice.
What about the Queue Class or Generic Queue Class?
Unfortunetally, your question is too vague to answer with any real detail. If this is something you want managed outside the primary application then a Windows Service would be a little more appropriate then creating a Console... From an integration and lifecycle management perspective this provides a nice foudation for adding other features (e.g. Performance Counters, Hosted Management Services in WCF, Remoting, etc...). MSMQ is great although there is a bit more involved in deployment. If you are willing to invest the time, there are a lot of advantanges to using MSMQ. If you really want to create your own point to point queue, then there are a ton of examples online that can serve as an example. Here is one, http://www.smelser.net/blog/page/SmellyQueue-(Durable-Queue).aspx.

Categories