Do some work after the response in ASP.NET Core

I see this has never been answered, but actually have a solution. The simple solution:

public async Task<IActionResult> Request([FromForm]RequestViewModel model, string returnUrl = null)
{
    try 
    {
      var newModel = new ResponseViewModel(model);
      // Some work 
      return View("RequestView",newModel)
    }
    finally
    {
        Response.OnCompleted(async () =>
        {
            // Do some work here
            await Log(model);
        });
    }
}

The secure solution, as OnCompleted used to be called before the response being sent, so delaying the response:

public static void OnCompleted2(this HttpResponse resp, Func<Task> callback)
{
    resp.OnCompleted(() =>
    {
        Task.Run(() => { try { callback.Invoke(); } catch {} });
        return Task.CompletedTask;
    });
}

and call Response.OnCompleted2(async () => { /* some async work */ })


Building on Jeans answer and a question and answer on the try - return - finally pattern, the try and finally blocks can be removed (if you don't really want to catch an exception).

This leads to the following code:

public async Task<IActionResult> Request([FromForm] RequestViewModel model, string returnUrl = null)
{
    var newModel = new ResponseViewModel(model);

    // Some work 

    Response.OnCompleted(async () =>
    {
        // Do some work here
        await Log(model);
    });

    return View("RequestView", newModel);
}