1

Say I have the following methods, in my ASP.NET 5 Web API:

//(in a different class)
public static async Task SendStatus(string message)
{
    await SendStatusMessage(message); //sends a status message to the client
}

[HttpGet("api/dowork")]
public async Task<IActionResult> DoWork()
{
    await SendStatusToClient("starting to do work!");

    //when it reaches this point, it should run the code in the background

    await DoTheActualWork();
    await SendStatusToClient("finished work!");


    //I want the control back after it starts running the above code in the background, to send a 200 status code 
    return Ok();
}

This is how it should run:

  1. It sends a status message, stating that it has started doing the work.
  2. It does the work, and after the work is done, sends a status message. All of this should be done in the background.
  3. Return a 200 (OK) status code to the user who requested the work. The actual work takes a significant amount of time and should still be running in the background.

How would I achieve this?

ZeroSkill
  • 47
  • 5
  • You have to write your own middleware if you want precise control over http output. In your example you can do some tasks in parallel, but all http related stuff begins only when you return from method. – Alexey Rumyantsev Feb 13 '21 at 09:13
  • I don't want to precisely control http output, I want to start execution of the code in the background, and get control back so the method returns `Ok()` while it's still doing the work in the background. – ZeroSkill Feb 13 '21 at 09:18
  • The status message thing isn't related to the request handler, it's sending it somewhere else. – ZeroSkill Feb 13 '21 at 09:19
  • But you still cannot send `Ok` before all background processing in your method is done, if you want to do such things you have to go deeper and work on middleware level. – Alexey Rumyantsev Feb 13 '21 at 09:21
  • I didn't phrase it correctly, what I actually meant is that it informs another API that client X has requested that work is being done, and this does not use the asp.net request handler. – ZeroSkill Feb 13 '21 at 09:22
  • 3
    You cannot finish request and leave this background work running, no matter how you notify client in between, request to `DoWork` will wait until work is done, if you want real background processing you should look here https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-5.0&tabs=visual-studio – Alexey Rumyantsev Feb 13 '21 at 09:32

1 Answers1

2

There are two answers helpful to you.

  1. The first one, how to do it: Webapi2 - Return from controller action after one task completes, but continue with further Async processing
  2. The second one, why not do it: How to answer a request but continue processing code in WebApi

So what to do now. I would suggest the following steps:

  1. Create a queue. Either a database table an azure service bus queue, a rabbitmq queue or even a simple file or just a static memory structure. (Production loads require some persistence though)
  2. Create a long running task to process the queued items. Web api supports background tasks, but you could create a service a job on the cloud or a windows service or any other application or service that works.
Athanasios Kataras
  • 25,191
  • 4
  • 32
  • 61
  • Thank you very much. I looked at [this page](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-5.0&tabs=visual-studio#queued-background-tasks), used their example code, and injected the `BackgroundTaskQueue` into my application. I got working and it is working just like I wanted to. – ZeroSkill Feb 13 '21 at 12:45