Web API - Set each thread with the HttpRequestMessage id?

3.1k Views Asked by At

I have a web api coded in c#.

The web api uses functionality which is shared with other in-house components. it depends on single threaded flows and uses thread local storage to store objects, and session information. Please don't say if it's good or bad, that's what I have to deal with.

In the web api I've implemented a custom message handler (DelagatingHandler) with SendAsync

protected async override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)

which is based on TPL and sometimes switches threads, and when this happens, my thread based functionality gets messed up, since I'm losing the thread context and all data assigned to it.

My idea is to uniquely identify the HttpRequestMessage, I think using the correlation id should be sufficient for it

var requestId = request.GetCorrelationId();

But I want to store the correlation Id of the HttpRequestMessage per each thread that is allocated in the Task.

So my question is basically if I can identify a thread that's being allocated under a specific Task and allocate the id to it?

1

There are 1 best solutions below

1
On BEST ANSWER

For context related problems, you can use CallContext.LogicalSetData and CallContext.LogicalGetData, which is merely an IDictionary<string, object> which flows between contexts, and has a copy-on-write (shallow copy) semantics.

Since your data is immutable (according to the docs), you can map your correlation id to your threads managed thread id:

protected async override Task<HttpResponseMessage> SendAsync(
                         HttpRequestMessage request, 
                         CancellationToken cancellationToken)
{
    var correlationId = request.GetCorrelationId();
    var threadId = Thread.CurrentThread.ManagedThreadId;

    CallContext.LogicalSetData(correlationId.ToString(), threadId);
}

And later retrieve if to make sure you're on a "valid thread".

A good read on call context with async-await can be found here.