InvalidCastException из сеанса StateServer
Сайт, который я написал, испытывает странную проблему, из-за которой он внезапно не распознает элементы, сохраненные в сеансе, сразу после того, как я сделал какое-либо обновление кода. Я искал Stackru / google / etc и вижу, что некоторые другие люди имеют такую же проблему, но нигде не могут найти решение.
Вот примерно то, что происходит:
Если я добавлю товар в свою корзину, он сохранит List<BasketItem>
в сессии. Если я затем обновлю некоторый код (не BasketItem), переменная сеанса все еще существует, но.NET, похоже, не думает, что это List<BasketItem>
хотя это определенно так.
Когда я пытаюсь получить список элементов корзины после изменения кода, он выдает InvalidCastException
что просто не имеет никакого смысла, так как он в основном пытается сказать, что типы, между которыми он конвертируется, различны, даже если это не так.
Исключение составляет:
System.InvalidCastException: [A] System.Collections.Generic.List
1[BasketItem] cannot be cast to [B]System.Collections.Generic.List
1 [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 и т. Д.),
Я ценю, что это скорее обходной путь вокруг проблемы, чем прямое решение, но это работает.