Почему статус HttpContext.Session меняется на disposed?

#c# #asp.net-core-3.1

#c# #asp.net-core-3.1

Вопрос:

Я пытаюсь сохранить токен, который я получаю от внешнего API в сеансе.

фрагмент кода, касающийся этого;

         [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.Сессия.setValue(«Токен», «тест»);

в этой части не возникает никакой ошибки, но вторая та же строка кода выдает ошибку после getToken().

связанная ошибка

Система.ObjectDisposedException: ‘IFeatureCollection был удален. Имя объекта: ‘Коллекция’.’

Также 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;
        }
 

Ответ №1:

Проблема в том , что вы используете async void . Эти обещания не могут быть выполнены, и их семантика в конечном итоге сильно отличается от обычной Task . Ваше удаление происходит рано, потому что инфраструктура просто предполагает, что ваш Post метод завершен (он не может сказать иначе).

Измените подпись Post to be:

 public async Task Post()
 

Пожалуйста, обратите внимание, что это async void должно быть ограничено обработчиками событий.

Комментарии:

1. Хорошо, я понял, почему это так. Тем не менее, я командую await , и я ожидаю, что метод ожидает там.

2. @ilyasvarol тогда нет, вы не понимаете , почему это так. Пожалуйста, прочитайте больше async/await и о подводных камнях async void

3. в любом случае, еще раз спасибо! Я собираюсь узнать больше информации об этом.

Ответ №2:

Я не уверен в использовании HttpContext. У вас есть IHttpContextAccessor в asp.net ядро. Я думаю, что для токена магазина вы можете использовать это

 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; }
}
 

А затем добавьте этот персонал в свой DI, подобный объекту scope, и используйте его в контроллерах через ServiceProvider.

Комментарии:

1. спасибо за ваши усилия, но я просто хочу очень просто сохранить токен в сеансе.

2. Я думаю, что «httpcontext» меняется после действия post в «getToken ()». Если я заблокирую это, я решу свою проблему.

3. Это потому, что вы неправильно используете async void