【问题标题】:InvalidCastException from StateServer session来自 StateServer 会话的 InvalidCastException
【发布时间】:2012-01-14 20:35:09
【问题描述】:

我编写的一个网站遇到了一个奇怪的问题,即在我对代码进行任何更新后,它突然无法立即识别会话中存储的项目。我搜索了 Stackoverflow / google / 等,可以看到其他一些人有同样的问题,但在任何地方都找不到解决方案。

大致如下:

如果我将一个项目添加到我的购物篮,它会在会话中存储一个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,Version=2.0.0.0,Culture=neutral, 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"];

目前我使用'as cast',所以我不会出错,但这确实意味着更新代码时用户的购物篮会丢失。

任何建议将不胜感激!

干杯

提姆

【问题讨论】:

  • 我想知道这是否与两种不同的 BasketItem 类型有关;您能否确认:是否有可能是从 1 个构建版本 saved 然后从另一个构建版本 loaded 加载的? BasketItem 是否可能来自 2 个不同的程序集?是否有可能您在同一个场中有不同的机器具有不同的构建版本,或者每台机器都在独立构建?
  • (错误消息告诉我们List&lt;&gt;而不是BasketItem,这有点烦人,很难看出字符串是否会告诉我们一些明显的事情)
  • 嗨,马克,关于您的第一条评论——是的,我想 .NET 可能会从两个不同的程序集加载 BasketItem。每当 App_Code 发生更改时,我认为 .NET 会将其重新编译为新程序集。
  • 当然可以。

标签: c# asp.net session-state .net stateserver


【解决方案1】:

由于BinaryFormatter 存储基础类型数据的方式,这种类型 问题非常常见,如果它们不能完全解决与您想到的 BasketItem 相同。最常见的是,在更改应用程序/库的版本时,或者当不同的服务器具有不同的状态时,这会造成伤害。

我的强烈建议是:不要让它使用BinaryFormatter 来存储状态!它不是对版本非常友好,无论是在这方面还是在一个类型中 的其他一些问题上。如果可能的话,我建议您考虑使用强大的基于合同的数据(意思是:几乎任何东西都不是BinaryFormatter / NetDataContractSerializer)。例子:

  • 您可以使用JavaScriptSerializer 并存储基本的string 数据
  • 您可以使用XmlSerializer 并存储基本的string 数据
  • 如果你想要二进制,你可以使用 protobuf-net 并存储 byte[] 的数据

您显然会使用辅助方法来存储/检索您的数据,通常使用通用的void Store&lt;T&gt;(string key, T object)T Retreive&lt;T&gt;(string key),在内部根据需要使用typeof(T)。这样做的好处是,存储的数据现在与任何特定实现无关,并且可以被您的应用程序的其他版本使用(因为没有任何东西与类型相关),如果需要,甚至可以被其他平台(Java、php 等)使用.

我很欣赏这是解决问题而不是直接的解决方案 - 但是:它有效。

【讨论】:

  • 感谢您的详细解答!我喜欢您关于将 BasketItem 类序列化为 Xml 并将其作为字符串存储在会话中的建议。我看不出 .NET 会有任何问题,所以我肯定会尝试一下!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-11
  • 2010-11-29
  • 2010-09-10
  • 2013-03-07
  • 2013-09-27
  • 2012-10-08
  • 1970-01-01
相关资源
最近更新 更多