【问题标题】:Whats the best way to handle variables in multiuser asp.net site在多用户 asp.net 站点中处理变量的最佳方法是什么
【发布时间】:2021-10-30 05:25:27
【问题描述】:

我为工作创建了一个 asp.net 页面,允许客户在 AD 中查找用户,然后请求将他们添加为 Rightfax 号码的代表,也可以搜索该号码。现在,我将项目后端和前端使用的公共变量存储在 CurrentSession 类中,该类由 supposed 对每个用户唯一的页面继承,但我仍然看到偶尔出现的问题其中变量将从一个会话“流血”到另一个会话。有时我会转到该页面,AD 用户列表中已经填充了来自另一个会话\用户的用户。

我想知道在这种情况下存储变量的最佳方法是什么。我应该使用 cookie 而不是当前的会话类吗?是否有任何关于 asp.net 页面变量管理的好的指南/教程?我通常是桌面开发人员,所以我对这类问题不是特别熟悉。

【问题讨论】:

  • 在 IIS Admin 中,找到该站点正在使用的应用程序池,并在其“高级设置...”中确保“最大工作进程”设置为 1。
  • @AndrewMorton 为什么?这样做的目的是什么?
  • 请张贴minimal reproducible example 显示您的代码受此影响。与其问“最好的编码方法是什么”,不如将问题表述为“这是我尝试过的,但由于 X 而无法正常工作,我该如何解决?”
  • @mason 名称已更改,但此问题仍然存在:ASP.NET session state and multiple worker processes。我们不妨先检查简单的事情。
  • @AndrewMorton 很高兴知道。您最初的评论缺乏这种背景,这就是我问的原因。看起来您只需要为网络花园模式执行此操作。我已经好几年没听说过这个词了,我想知道它是否还在。

标签: asp.net vb.net asp.net-web-api global-variables


【解决方案1】:

整个跳转到网络,会话管理或变量管理是一个巨大的话题。这通常是一个挑战,因为 concpets 与桌面非常不同。

所以,我的意思是,当用户单击一个按钮时,该网页被发布到服务器。页面被找到,加载,变量从头开始。后台代码运行,页面被发送回客户端,页面服务器端被丢弃!

因此,由于网页的所谓“无状态”性质,上述挑战是一个新的挑战。

至于会话流血给其他用户?哼,这不应该发生。但是, session() 可能非常脆弱。由于超时,由于代码中的一些执行错误,应用程序池可以并且经常会重新启动。

因此,我强烈建议您运行脚本并打开基于 SQL servre 的会话管理。完成后, session() 就成为了防弹 - 并且始终有效。

至于价值流向其他用户?不可能 - 我没看到。

(当然,您没有提及或说明您使用的身份验证提供程序(或者即使用户必须登录)。

但是,虽然我经常使用会话,甚至将值从一页传递到下一页? (URL 中绝对讨厌的参数 - 如果包含 PK id 等内容,则会造成混乱且通常存在安全风险)。

然而,一些大网站说像亚马逊在 URL 中使用参数和值很多。从那时起,他们就这样做了,服务器端不会超载,并且必须跟踪或保存这些值。但是,除非您构建下一个 facebook 或大型 + 高容量网站,否则 session() 是保持代码活跃值的标准方法。

但是,假设我们抛出一个网格,并且用户选择了该产品?

我们在 session() 中设置说 PK id,然后跳转到下一页说要买那个房子?

好吧,现在如果您打开一个新选项卡 - 甚至是不同的浏览器,启动该网格,选择一个房子并跳转到页面以显示该信息?您不能使用 session,因为如前所述,它会覆盖其他页面中的值。

所以,你可以尝试构建一堆花哨的类和各种倒立,但我只是简单地将 session() 值传递给 ViewState。

ViewState 是每页的,而 session() 对那个用户来说是全局的。

所以,如果我需要 10 个变量和值用于应用程序的给定部分,可以这样说:

<Serializable>
Public Class clsProjectInfo

    Public ContactID As Integer = 0
    Public ContactGeneralID As Integer = 0
    Public PortalComp As String = ""
    Public ProjectHeaderID As Integer = 0
    Public QuoteNum As Integer = 0
    Public UploadGroup As Integer = 0
    Public txtNotes As String = ""
    Public ProofID As Integer = 0

End Class

所以在页面中说我们选择项目 - 设置一整套值?

那么上面的 var 将在 session() 中,但仅用于传递到下一页。

所以需要所有 aobve 值才能工作的项目视图页面?

页面加载代码如下所示:

Dim cPinfo As New clsProjectInfo

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    If IsPostBack = False Then

        cPinfo = Session("Pinfo")
        ViewState("Pinfo") = cPinfo

    Else

        cPinfo = ViewState("Pinfo")

    End If

所以我们只使用 session 将“一堆值”传递到下一页,但我们做的第一件事总是从 session() 转移到 viewstate。这样,如果用户打开另一个选项卡,或在第二个浏览器中选择不同的房子,跳转到视图详细信息,我们只使用 session() 将值传递到下一页,但从那时起,总是使用 ViewState .

现在上述简单的想法可能不适用于所有情况,但适用于大多数情况。

因此,不要采用大量的 session() 值,并且与往常一样,即使在桌面上,也不需要全局变量和值。

因此,给定用户的 session() 肯定会经常“踩”在应用程序的其他部分之上。如果 session() 在不同用户之间溢出?这不应该发生,永远不会发生,并且如前所述,这意味着这里出了问题。

即使是桌面软件?每个表单、页面或应用程序的一部分往往具有并且需要一组值。所以,我按照上面的方法构建了平面简简单类。然后你可以很容易地传递一个包含 5-10 个变量的类的东西。这样我就不会在 session() 中得到 50 个变量——从编码的角度来看,这是一场噩梦(更不用说记住变量了)。但是上面通过了一个类,然后你只通过了一个东西,你也得到了 intel-sense。

毫无疑问,这组变量通常必须传递给例程。所以在上面之前,我经常喜欢将 5-6 个值传递给某个函数或子 - 真是太棒了。

这么老的方式:

    Call SaveAfterUpload(AjaxFileUpload1, session("QuoteNum", session("ContactID",
                 session("UploadGroup"), strCleanFile, session("txtNotes"), session("PortalComp")

但现在我们可以走了:

    Call SaveAfterUpload(AjaxFileUpload1, cPinfo.QuoteNum, cPinfo.ContactID,
                         cPinfo.UploadGroup, strCleanFile, cPinfo.txtNotes, cPinfo.PortalComp)

但是,再一次,既然我们有那个类,那么上面现在变成了

    Call SaveAfterUpload(AjaxFileUpload1, cPinfo)

所以,不要将一大堆值放入 session()。

创建值的“分组”。

还有什么是超级棒的?

通常一些客户端 JavaScript 代码需要这些值。

因此,您最终会为这些值投入一大堆隐藏字段或隐藏控件。

但是,上面的课程呢?我可以通过 + 让整个客户端像这样:

        cPinfo = ViewState("Pinfo")   ' this no doubt occured on page load

        ' copy Pinfo to browser side 
        MyUpLoadInfo.Value = JsonConvert.SerializeObject(cPinfo)

MyUpLoadInfo 只是一个简单的 asp.net 隐藏字段,如下所示:

            <asp:HiddenField ID="MyUpLoadInfo" runat="server" ClientIDMode="Static" />

但是,现在代替那些 5-6 个隐藏字段,我现在有上面的 cPinfo 供客户端使用。

例如:

               MyUpLoadInfo = document.getElementById("MyUpLoadInfo")
               Pinfo = JSON.parse(MyUpLoadInfo.value)

               // now I have all values such as
               Pinfo.txtNotes
               Pinfo.QuoteNum

因此,通过构建该类或变量集,我现在可以一次将整个混乱传递给客户端,现在我的 JavaScript 代码可以非常轻松地在客户端使用所有这些变量!

事实证明,对于典型应用程序的每个部分?

 about 5-10 variables are only required

 often they are required client side - and with above we can

 Most if not ALL of the routines in that application part need those vars
 (including subs and functions, so now we can pass 5-10 values, and we don't
  have huge long list of messy parameters in all of those subs and functions).

我们可以修改类 - 添加更多变量,现在十几个例程都有这个额外的变量 - 但是我们不更改代码,甚至更改子/函数调用以在该代码中添加额外的新变量. (如果我们需要/要求浏览器代码的那组值,这适用于客户端 js 代码。)。

因此我们没有大量的全局变量。

我们最终不会得到大量单独的会话值。

我们极大地提高了将这些值传递给子/函数的能力。

我们甚至可以轻松地将这组值传递给客户端。

因此,任何全局变量都可以在会话中,但这些全局变量绝不可用于在页面之间传递值以及对应用程序的给定部分进行代码调用。

如果您希望用户支持多个页面或浏览器?然后采用在第一页加载时将该会话类转移到视图状态的标准。

【讨论】:

  • 非常感谢您的回复!这是很多有用的信息,我会看看我可以在我的项目中实现什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-18
  • 2012-04-08
  • 1970-01-01
  • 1970-01-01
  • 2017-04-26
  • 2016-05-26
  • 2011-03-19
相关资源
最近更新 更多