Store & Pass Call Context in .NET

How to store and pass some context down the call stack in .NET. Via AsyncLocal / AsyncLocal<T>

Store & Pass Call Context in .NET
AsyncLocal in .NET - for async/await call context

The main and only assumption is that you're using the Task API (a.k.a. async/await).

The scenario, as it often happens, is that you want to send some arbitrary data objects (aka context) down the call stack and you don't want to pollute the methods' signatures with such arguments.

Think here about Security Contexts, User Contexts, Logging Contexts...

The way to do this in .NET is via AsyncLocal's Value property.

When you set the AsyncLocal<T>.Value, it will be available anywhere and only down the current async/await call chain.

static class UserContext
{
    static AsyncLocal<User> userContext;
    
    public User CurrentUser
    {
        get => userContext?.Value;
        set => userContext = new AsyncLocal<User>().And(x => x.Value = value);
    }
}

class Worker
{
    public async Task DoWork()
    {
        UserContext.CurrentUser = await httpContextProvider.GetCurrentUser();
        
        await DoProcessingA();
        await Task.WhenAll(
            DoSomeMoreAsyncProcessing(),
            DoEvenMoreAsyncProcessing()
        );
    }
    
    async Task DoProcessingA()
    {
        //unique per async call chain
        User currentUser = UserContext.CurrentUser;
    }
}