InvalidCastException из сеанса StateServer

Сайт, который я написал, испытывает странную проблему, из-за которой он внезапно не распознает элементы, сохраненные в сеансе, сразу после того, как я сделал какое-либо обновление кода. Я искал Stackru / google / etc и вижу, что некоторые другие люди имеют такую ​​же проблему, но нигде не могут найти решение.

Вот примерно то, что происходит:

Если я добавлю товар в свою корзину, он сохранит List<BasketItem> в сессии. Если я затем обновлю некоторый код (не BasketItem), переменная сеанса все еще существует, но.NET, похоже, не думает, что это List<BasketItem> хотя это определенно так.

Когда я пытаюсь получить список элементов корзины после изменения кода, он выдает InvalidCastException что просто не имеет никакого смысла, так как он в основном пытается сказать, что типы, между которыми он конвертируется, различны, даже если это не так.

Исключение составляет:

System.InvalidCastException: [A] System.Collections.Generic.List1[BasketItem] cannot be cast to [B]System.Collections.Generic.List1 [BasketItem]. Тип A происходит от "mscorlib, версия =2.0.0.0, культура = нейтральная, PublicKeyToken=b77a5c561934e089" в контексте "LoadNeither" в расположении "C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll", Тип B происходит от "mscorlib, версия =2.0.0.0, культура = нейтральная, PublicKeyToken=b77a5c561934e089" в контексте "LoadNeither" в расположении "C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll",

Я использую StateServer для состояния сеанса и запускаю ASP.NET 3.5 SP1, если это помогает.

Код, который я использую ниже:

// for setting the basket
List<BasketItem> basketItems = new List<BasketItem>();
Session["basket"] = basketItems;

// for getting the basket
List<BasketItem> basketItems = (List<BasketItem>)Session["basket"];

На данный момент я использую "как приведение", поэтому я не ошибаюсь, но это означает, что корзина пользователя теряется при обновлении кода.

Любые советы будут высоко ценится!

ура

Тим

1 ответ

Решение

Этот тип проблемы довольно распространен из-за того, как BinaryFormatter хранит данные базового типа, которые могут вызвать проблемы, если они не разрешаются точно так же BasketItem что ты имел в виду. Чаще всего это причиняет боль при смене версии вашего приложения / библиотеки или при наличии разных серверов с разными состояниями.

Мой сильный совет здесь: не позволяйте этому использовать BinaryFormatter хранить состояние! Это не очень дружественно к версии, как в этом отношении, так и в некоторых других типах. Если это возможно, я призываю вас рассмотреть сильные данные на основе контракта (то есть: практически все, кроме BinaryFormatter / NetDataContractSerializer). Примеры:

  • вы могли бы использовать JavaScriptSerializer и хранить основные string данных
  • вы могли бы использовать XmlSerializer и хранить основные string данных
  • если вы хотите двоичный файл, вы можете использовать protobuf-Net и вызвать byte[] данных

Тогда вы, очевидно, будете использовать вспомогательные методы для хранения / извлечения ваших данных, обычно с void Store<T>(string key, T object) а также T Retreive<T>(string key), с помощью typeof(T) внутренне по мере необходимости. Преимущество этого заключается в том, что хранимые данные теперь нейтральны по отношению к какой-либо конкретной реализации и могут использоваться другими версиями вашего приложения (поскольку ничто не зависит от типа), и даже, если необходимо, другими платформами (Java, php и т. Д.),

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

Другие вопросы по тегам