ASP.NET 网站 + SQL 支持的会话

发布于 2024-10-20 12:05:58 字数 731 浏览 11 评论 0原文

我们正在使用带有动态编译的 ASP.NET 网站项目,最近转移到 SQL Server 支持的会话状态并开始出现奇怪的错误。我已经找出导致此问题的原因,但我不知道解决该问题的最佳方法。

在本地主机上重现的步骤(启用 sql 会话):

  • 将 AppCode 中定义的对象(假设它是一个 DanObject)放入会话中。

    Session["x"] = new DanObject();

  • (Session 被序列化到数据库)

  • 修改应用程序代码中的某些内容,导致站点在下一个请求时重新编译
  • 向访问该会话的任何页面发出请求

错误是“无法找到程序集'App_SubCode_CS.rmdbqb81,版本= 0.0.0.0,文化=中性,PublicKeyToken = null'。”

发生的情况是,每次编译 AppCode 时,它​​都会进入一个随机命名的程序集。当我的Session第一次序列化时,AppCode恰好被命名为AppCode_123。当我修改我的应用程序时,AppCode 现在是 AppCode_456。但是,存储在我的数据库中的会话有一个在 AppCode_123 中定义的对象。当会话尝试对 DanObject 进行二进制反序列化时,它会崩溃,因为它找不到 AppCode_123。

解决这个问题最简单的方法是什么?
*请不要说切换到 Web 应用程序——我们的代码库非常庞大,目前还不可行:)

We are using an ASP.NET web site project with dynamic compilation, and recently moved to a SQL Server backed session state and started getting a strange error. I've figured out what is causing this, but I don't know the best way to resolve it.

Steps to reproduce on localhost (with sql session enabled):

  • Place an object defined in AppCode, lets say it's a DanObject into the session.

    Session["x"] = new DanObject();

  • (Session is serialized to the database)

  • Modify something in app code, causing the site to recompile on the next request
  • Make a request to any page that accesses the session

The error is "Unable to find assembly 'App_SubCode_CS.rmdbqb81, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'."

What's happening is that every time AppCode is compiled, it goes into a randomly named assembly. When my Session is serialized the first time, AppCode happened to be named AppCode_123. When I modified my application, AppCode is now AppCode_456. However the Session stored in my database has an object defined in AppCode_123. When the Session tries to binary deserialize the DanObject, it blows up because it can't find AppCode_123.

What is the simplest way I can fix this?
*Please don't say switch to Web Application--our code base is huge and it is not feasible at this point :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

榕城若虚 2024-10-27 12:05:58

在 DanObject 周围使用显式命名空间

Use an explicit namespace around DanObject

埋葬我深情 2024-10-27 12:05:58

好的,第二个最简单的解决方案:
将此类的代码移至单独的程序集库。这样,当序列化器看到该类时,它将有一个已知的好名称可以使用。当然,这会消除您直接编辑 app_code 目录的能力……无论如何您都不应该这样做。

第三个最简单(也是最好的)解决方案:
不要将对象放入会话中。如果您需要几个属性,那么将这些属性存储为常规字符串是一回事。

<slight_rant>

说真的,将完整的对象放入会话中并不是它的目的。

请参阅我的答案(会话和存储对象),了解更多信息您不想这样做的原因。

最后一点:这个问题似乎只是一个问题,因为你们持续会话并直接更改 Web 服务器上的代码。别再这样做了。在本地进行更改(并测试它们),然后预编译并部署您的站点,最后在部署后使会话无效。按照标准化的发布时间表执行此操作,以便每个人都知道停机时间。

</slight_rant>

Okay, second easiest solution:
Move the code for this class instead a separate assembly library. This way when the serializer sees the class it will have a known good name to work from. Of course, this removes your ability to make edits directly to the app_code directory... which you shouldn't be doing anyway.

Third easiest (and the best one) solution:
Don't put objects into session. If there are a couple properties you need, that's one thing, store those properties as regular strings.

<slight_rant>

Seriously, putting full objects into session is NOT what it was built for.

See my answer here ( Sessions and storing objects ) for a little more information on the reasons why you don't want to do this.

And, onto the final note: This problem seems to only be an issue because you guys are persisting session AND making changes directly to the code on the web server. Stop doing that. Make your changes (and test them) locally, then precompile and deploy your site, finally invalidate session once it's deployed. Do this on a normallized release schedule so everyone knows when the downtime is.

</slight_rant>
孤单情人 2024-10-27 12:05:58

问题是我们在 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,并且框架似乎无法处理这种情况。因此,如果您有 2 个网络服务器共享 Sql 支持的会话,则 Foo 类在服务器 A 上编译为 "App_SubCode_FN.random1, Foo" ,并且在服务器 A 上编译为 "App_SubCode_FN.random2, Foo"如果用户在会话中从服务器 A 获取 Foo,然后他的下一个请求转到服务器 B,则服务器 B 将无法反序列化 Foo,因为它找不到名为 "App_SubCode_FN 的程序集.random1"

该问题可以通过摆脱旧的 VB 代码(允许将应用程序代码编译为 .NET 更好地使用的单个程序集)或通过编写自定义 SerializationBinder + Sql Server 支持的会话的自定义实现来解决。

The problem was we had separate folders in App_Code for different code languages. This is why in the error message, it said "App_SubCode_CS..." instead of "App_Code...", because the specific class came from a CS code folder (for c# code). Each of these code folders (defined in web.config) get compiled into its own assembly.

Normally when you don't have multiple code folders AppCode, ASP.NET is able to serialize and deserialize objects compiled at different times or on different servers because the assembly name ("AppCode.randomstring") is stored with the class name in the serialized output. On deserialization, the framework calls System.Type.GetType() on the assembly + class name, and that function has a special case to handle assembly names starting with App_Code, where if it doesn't find an assembly named exactly the same, but it does find one that starts with App_Code, it uses that assembly to load the class.

When you have language folders in App_Code, the generated assemblies are named like: App_SubCode_FOLDERNAME.randomstring, and the framework doesn't seem to handle this case. So if you have 2 webservers sharing a Sql backed session, class Foo is compiled as "App_SubCode_FN.random1, Foo" on server A, and "App_SubCode_FN.random2, Foo" on server B. If a user gets a Foo in his session from server A, and then his next request goes to server B, server B will be unable to deserialize the Foo because it can't find an assembly named "App_SubCode_FN.random1".

The problem can be solved by getting rid of your old VB code (allowing app code to be compiled into a single assembly that .NET plays more nicely with), or by writing a custom SerializationBinder + a custom implementation of the Sql Server backed session.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文