ilyas varol
ilyas varol

Reputation: 968

Why is HttpContext.Session status changing to disposed?

I'm trying to store token I get from external api on session.

code snippet concerning this;

        [HttpPost]
        public async void Post()
        {
            if (HttpContext.Session.GetValue<User>("Token") == null)
            {
                HttpContext.Session.SetValue("Token", "test");
                var res = await _loginBusiness.GetToken();
                HttpContext.Session.SetValue("Token", res);
            }
        }

HttpContext.Session.SetValue("Token", "test");

in this part, it doesn't occur any error but second the same code line give an error after GetToken().

related error

System.ObjectDisposedException: 'IFeatureCollection has been disposed. Object name: 'Collection'.'

Also GetToken():

        public async Task<User> GetToken()
        {
            String url = "login/login";

            var client = httpClientFactory.CreateClient("VoiceScope");

            var postRes = await client.PostAsync<User>(new UserLogin(), url);

            return postRes;
        }

Upvotes: 1

Views: 3390

Answers (2)

pinkfloydx33
pinkfloydx33

Reputation: 12779

The problem is that you are using async void. These promises can't be observed and their semantics end up a lot different from a normal Task. Your disposal is happening early because the infrastructure just assumes your Post method has completed (it has no way to tell otherwise).

Change the signature of Post to be:

public async Task Post()

Please note that async void should be limited to event handlers.

Upvotes: 8

Stanislav Muryndin
Stanislav Muryndin

Reputation: 97

I am not sure about using HttpContext. You have IHttpContextAccessor in asp.net core. I think for store token you can use this

public class UserContext
{
    public UserContext(IHttpContextAccessor context)
    {
        Token = GetAccessToken(context);
    }

    private static string GetAccessToken(IHttpContextAccessor contextAccessor)
    {
        var identity = (ClaimsIdentity)contextAccessor?.HttpContext?.User?.Identity;
        return identity?.Claims.FirstOrDefault(x => x.Type == "token")?.Value;
    }


    public string Token { get; }
}

And then, add this staff in your DI like scope object and use it in controllers via ServiceProvider.

Upvotes: 2

Related Questions