loading...

Get your C# WebAPI controller to keep processing a request after returning 200 OK

deanashton profile image Dean Ashton ・1 min read

Alt Text

Ever needed a "fire and forget" solution where a client calls a C# WebAPI controller that does something long running, but doesn't really care about the result?

For example, say you have a job scheduling system that runs a series of tasks and one of them is a call to a C# WebAPI service to create something like an export of data from a SQL Server table to a file.

Problem

The table is large and the export will tie up the job scheduling system from running the rest of the tasks in the process, or timeout the job scheduling process. And the result of the WebAPI service doesn't mean anything to the end result of the process, with the WebAPI reporting errors in another way such as by email.

Solution

Make the C# WebAPI report a HttpStatus code of 200 OK and say that the request is complete to the calling client, while still continuing to work on the request in the background.

For this fire and forget functionality, in your WebAPI controller, do this:

public async Task<IActionResult> Post(string id)
{
    try
    {
        return Ok("Request submitted successfully");
    }
    finally
    {
        Response.OnCompleted(async () =>
        {
            await DoProcessing(id);
        });
    }
}

The key is the "Response.OnCompleted" part, which allows your code to execute even after reporting HttpStatus 200 OK to the client.

Posted on by:

deanashton profile

Dean Ashton

@deanashton

Software developer interested in C#, .NET, Azure, SQL Server, NoSQL, Angular, React, Vue

Discussion

pic
Editor guide
 

I have a similar situation in my webApi. The returned value is an entity , which needs long processing as the SQL query is complex (could take even 10-20 seconds). Is this a viable solution to return a value in the finally branch?

 

Hi Zoltan, sorry for the late reply. Unfortinately I don't think so. This method ha already returned the result by the time you would finish processing. It's really only for things like exporting data to a file or sending a message in a queue for later processing (where the output of the processing is not returned to the caller)

In my case, the processing time for the longrunning task was 1 hour :)