InvalidCastException из сеанса StateServer - PullRequest
3 голосов
/ 07 декабря 2011

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

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

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

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

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

System.InvalidCastException: [А] System.Collections.Generic.List 1[BasketItem] cannot be cast to [B]System.Collections.Generic.List 1 [BasketItem]. Тип А происходит от 'mscorlib, версия = 2.0.0.0, культура = нейтральная, PublicKeyToken = b77a5c561934e089 'в контексте' LoadNeither 'в место нахождения "C: \ Windows \ сборка \ GAC_64 \ mscorlib \ 2.0.0.0__b77a5c561934e089 \ mscorlib.dll. Тип B происходит от 'mscorlib, версия = 2.0.0.0, культура = нейтральная, PublicKeyToken = b77a5c561934e089 'в контексте' LoadNeither 'в место нахождения 'C: \ Windows \ сборка \ 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"];

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

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

Приветствия

Тим

1 Ответ

2 голосов
/ 07 декабря 2011

Этот тип проблемы довольно распространен из-за того, как 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 и т. Д.) .

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...