我们使用的是一个具有动态编译的ASP.NET网站项目,最近转移到Server支持的会话状态,并开始出现一个奇怪的错误。我已经知道是什么导致了这件事,但我不知道最好的解决方法。
在localhost上复制的步骤(启用sql会话):
DanObject();
DanObject到session.Session"x“=新的AppCode被序列化到数据库)的任何页面发出请求
错误是“找不到程序集'App_SubCode_CS.rmdbqb81,Version=0.0.0.0,Culture=neutral,PublicKeyToken=null‘”。
现在发生的情况是,每次编译AppCode时,它都会被随机命名为程序集。当我的会话第一次被序列化时,AppCode碰巧被命名为AppCode_123。当我修改我的应用程序时,AppCode现在是AppCode_456了。但是,存储在我的数据库中的会话有一个在AppCode_123中定义的对象。当会话尝试二进制反序列化DanObject时,它会因为找不到AppCode_123而崩溃。
我能解决这个问题的最简单方法是什么?
*请不要说切换到Web应用程序--我们的代码库很大,在这一点上是不可行的:)
发布于 2011-06-16 05:33:40
问题是我们在App_Code中为不同的代码语言有不同的文件夹。这就是为什么错误信息中写着“App_SubCode_CS.”而不是“App_Code.”,因为特定的类来自CS代码文件夹(用于c#代码)。每个代码文件夹(在web.config中定义)都被编译到自己的程序集中。
通常,当您没有多个代码文件夹AppCode时,ASP.NET能够序列化和反序列化在不同时间或不同服务器上编译的对象,因为程序集名称("AppCode.randomstring")与类名一起存储在序列化输出中。在反序列化时,框架对程序集+类名调用System.Type.GetType(),该函数有一个特殊情况来处理以App_Code开头的程序集名称,如果它找不到一个名称完全相同的程序集,但是它确实找到了一个以App_Code开头的程序集,它使用该程序集加载该类。
当App_Code中有语言文件夹时,生成的程序集命名为:App_SubCode_FOLDERNAME.randomstring,而框架似乎不处理这种情况。因此,如果有两个and服务器共享一个Sql后台会话,则在服务器A上将类Foo编译为"App_SubCode_FN.random1, Foo",在服务器B上将类Foo编译为"App_SubCode_FN.random2, Foo"。如果用户在会话中从服务器A获得Foo,然后他的下一个请求转到服务器B,服务器B将无法反序列化Foo,因为它找不到名为"App_SubCode_FN.random1"的程序集。
这个问题可以通过摆脱旧的VB代码(允许将应用程序代码编译成.NET更好地处理的单个程序集)或编写自定义SerializationBinder + Server支持会话的自定义实现来解决。
发布于 2011-03-04 17:32:53
在DanObject周围使用显式命名空间
发布于 2011-03-04 18:38:13
好的,第二个最简单的解决方案:
移动该类的代码,而不是单独的程序集库。这样,当序列化程序看到类时,它将有一个已知的好名称可供使用。当然,这消除了直接对app_code目录进行编辑的能力.反正你也不该这么做。
第三最简单(也是最好的)解决方案:
不要将对象放入会话中。如果您需要一些属性,这是一回事,将这些属性存储为常规字符串。
<slight_rant>说真的,将完整的对象放入会话并不是构建它的目的。
关于您不想这样做的原因,请参阅我的答案( Sessions and storing objects ),以获得更多信息。
最后,注意:这个问题似乎只是一个问题,因为你们正在持久化会话,并直接对web服务器上的代码进行更改。别这么做了。在本地进行更改(并对其进行测试),然后预编译和部署站点,最后在部署后使会话失效。这样做是在一个标准化的发布时间表上进行的,这样每个人都知道什么时候停机。
</slight_rant>https://stackoverflow.com/questions/5197140
复制相似问题