Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do C# Ajax Comet via WebAPI2?

I have a C# ASP.Net (non MVC) project that uses Ajax Comet long-polling. A web page makes a HTTP call to an endpoint handled by a class implementing IHttpAsyncHandler.

If there is nothing to report (within n seconds) to the web page, an empty HTTP response is sent, and the webpage re-calls. If there is something to send, and update is sent, and the webpage processes and re-calls. This is pretty standard push technology, and works very well.

Now I am trying to add API endpoints, using WebAPI2, non-MVC. I have synchronous controllers working, based on the ApiController class.

I would like to set up push technology for the API calls, so that API users do not have to poll for updates.

Similar to the method above, the API endpoint call is received, and the context is stored. If a timeout expires, the call is returned empty, and the caller is expected to call again. If data updates within the timeout, the data is returned to the caller, and the caller is then expected to call again and wait for more updates.

The problem is that there seems to be no asynchronous version of ApiController. The aim is to free the thread that is handling the API call, to return it to the pool, and then when there is data available, or the timeout expires, a worker thread is used to return the response.

How can I set up an ApiController so that the thread processing the call is freed, the call context is stored, and I can send a response to the call at a later point in time?

like image 913
Steve Hibbert Avatar asked Dec 07 '16 11:12

Steve Hibbert


1 Answers

You can use async/await to achieve what you want i.e.:

[HttpPost]
public async Task<HttpResponseMessage> LongRunningOperation([FromBody]Input obj)
{
    // Do what ever you need with input data        

    await WaitForEvent();        

    // Do what ever you need to return a response

    return someResponse;
}

In this example the Web API method is declared as async and in its body await operator was used to return a thread to a pool.

I assumed that in order to implement Comet you uses some kind of events. As far as I remember many years ago I used ManualResetEvent to do so. However, it can be anything else.

What is important is that WaitForEvent method should return something awaitable. In other words ManualResetEvent or other wait handle should be wrapped in a task. You can do that with AsyncFactory.FromWaitHandle method.

It is also worth reading this discussion about asyn/await in the context of Web API.

like image 155
Michał Komorowski Avatar answered Oct 05 '22 23:10

Michał Komorowski