Search code examples
c#.netasp.net-mvc

Private variables inside DelegatingHandler mixing values from other requests


We have a DelegatingHandler implemented that has some private variables and 2 of them are getting values from different parallel requests than their own even though they are not static variables

public sealed class XYZProxyHandler:DelegatingHandler
{
    private string _var1;
    private string _var2;

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var token = request.Headers.GetCookies().FirstOrDefault().Cookies.FirstOrDefault(x => x.Name.ToLower() == "access_token").Value;
        _var1 = GetVar1(token);
        _var2 = GetVar2(token);

Tried to make it as simple of code while including an important piece of code. In the above sample code, ideally _var1 and _var2 should get the values of its own request but for whatever reason, they sometimes get other request's values. I have instances of _var1 getting the value of another request but _var2 gets the value of its own request and vice-versa.

I have run into this type of behaviour before when a static variable is shared across requests but these are not static variables and hence I am not sure how it can happen or if it is something to do with DelegatingHandler implementation.

I have tried to test it but did not reproduce it and am working on the same with more variations of test data and this happens 50 times in a month maybe so not very often.

I am not sure if I am being tunnel visioned and not seeing something obvious or glaring.


Solution

  • The instance of DelegatingHandler-class is simultaneously consumed by all requests that the app receives so this behavior is predictable.

    I would get rid of any local variables and pass the required values directly:

    public sealed class XYZProxyHandler : DelegatingHandler
    {
       // If needed some thread-safe service, repo, etc can be passed in the constructor.
        /*
        private readonly ISmth _smth;
    
        public XYZProxyHandler(ISmth smth) 
        {
            _smth = smth;
        }
        */
    
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var token = request.Headers.GetCookies()
                .FirstOrDefault().Cookies
                .FirstOrDefault(x => x.Name.ToLower() == "access_token").Value;
            var _var1 = GetVar1(token);
            var _var2 = GetVar2(token);
            
            SomeMethod(_var1, _var2);
            
            // ..
        }
        
        private void SomeMethod(string one, string two) {
          
          
        }
    }