【问题标题】:ASP.Net VB: Need a better alternative to using public shared variablesASP.Net VB:需要更好的替代方法来使用公共共享变量
【发布时间】:2021-08-04 21:13:24
【问题描述】:

我一直在使用 VB 为 ASP.net 开发一个应用程序,现在我们正处于多个用户同时测试该应用程序的阶段。在开发应用程序时,我创建了一个包含用于访问 API 的函数的类,然后创建了几个带有自己的类的 Web 表单。在 API 类中,我声明了十几个公共共享变量,以便 web 表单和 API 类可以轻松共享和访问数据,最初我自己测试时效果很好,但现在其他人正在使用它,我遇到用户 X 将执行搜索并将结果保存到 API 类中声明的共享变量的问题,当用户 Y 之后使用该页面进行搜索时,他们的搜索结果与来自用户的结果混合显示十。

有什么更好的方法来处理变量以使它们对每个用户都是唯一的?我曾尝试在网络表单的类中将它们设为公共共享变量,但后来我遇到了值被重置并在回发时丢失的问题。

有没有办法创建一个类来存储每个用户或会话独有的变量并在一定时间后过期?

【问题讨论】:

  • 如果您像所有代码一样创建该类的新实例?那么你就没有任何问题了。您不能使用全局范围的静态类 - 对于应用程序来说是全局的 - 而不是用户。但是,如果您为每个用户创建类对象的新实例,那么该对象将仅适用于每个单独的用户。当然,鉴于网页是无状态的,那么就像所有变量一样 - 它们将超出范围。因此,在这种情况下,您需要使用 ViewState 或 session() 在每个用户基础上持久保存任何值或变量。对于简单的变量,可以使用页面上的隐藏字段。

标签: asp.net vb.net webforms


【解决方案1】:

听起来您需要会话变量,每个用户都是独一无二的。

要写一个会话变量:

Session("MySessionVariableName") = lblMyLabel.Text

读取会话变量:

lblMyLabel.Text = Session("MySessionVariableName")

当用户会话过期时,存储的值也会过期。

更多信息在这里: https://docs.microsoft.com/en-us/previous-versions/ms178581(v=vs.140)?redirectedfrom=MSDN

【讨论】:

    【解决方案2】:

    如果您像所有代码一样创建该类的新实例?那么你就没有任何问题了。

    您不能使用全局范围的静态类 - 对于应用程序来说是全局的 - 而不是用户。

    但是,如果您为每个用户创建一个类对象的新实例,那么该对象将仅适用于每个单独的用户。

    当然,鉴于网页是无状态的,因此与所有变量一样 - 在页面呈现并发送到客户端(浏览器)后,它们将超出范围。

    那么在这些情况下,要坚持价值观吗?

    您可以使用表单上的隐藏字段或控件来保存值。

    您可以在 URL 中包含参数 - 您经常在 Amazon.com 上看到这一点 - 他们将值 RIGHT 放在 URL 中 - 您可以看到它们! (但这通常是敏感值的安全问题 - 因为用户可以修改和弄乱 URL 中的这些参数)。

    对于每页的持久性,我强烈建议使用 ViewState。

    对于全局(每个用户),我强烈建议使用 session() 来保存值。但是,您要非常小心 session()。假设你要在网上买房。你把你要买的房子的PK或ID放在session()中。那么问题是如果用户打开第二页、另一个浏览器,甚至是一个新标签页? session() 值对用户来说是全局的。因此,现在如果他们打开了两个页面 - 您推入 session() 的 PK ID 将是您打开的最后一个页面。如果他们回到另一个显示不同房子的浏览器副本 - 如果他们点击“购买”并且您使用 session("HousePKID"),那么您将获得最后一个 session() 值。 (最后买错了房子!!!)。

    所以:

    Session() - 全局值 - 每个用户 - 效果很好。

    ViewState() - 每个用户,但也仅限于每个页面。

    所以,请记住并注意就像您当前的问题(静态类 - 由所有用户共享)一样,请记住 session() 非常适合将值传递到另一个网页/表单,但请注意请注意 session() 对于每个用户都是全局的。

    所以,我通常会使用 session() 将值传递到另一个页面,但在那个新页面上,我会将值(或类)传递给 ViewState,因此这种设计将允许多个页面工作 + 功能。

    所以,像所有代码一样 - 包括桌面代码?您可以(甚至应该)创建和使用您制作的自定义类的实例 - 但它们肯定最好不要是静态类,并且您必须在 ViewState、session() 中保留这些类。

    如前所述,对于简单值,您还可以在网页上使用隐藏控件,并将值推送到此类控件中 - 它们也会持续存在。

    事实上,asp.net 的学习曲线和技能很大程度上取决于您的经验,随着时间的推移,您会发​​现哪个是最佳选择。

    我有几页,我开始使用 session() - 它很简单,效果很好。但是请记住 session() 对一个用户来说是全局的,因此在您说存储一些产品 ID 密钥或类似的情况下?然后考虑该应用程序或用户是否可能打开了多个浏览器或选项卡。如果该值特定于所讨论的一个页面,那么您最好将该值从 session() 转移到 ViewState - 因为 ViewState 是按页面的 - 而不是每个用户的范围。

    例如,我有一个包含一堆值的类 - 用户在一个页面上做了各种事情,然后我需要将这些值转移到下一页。

    所以,我这样做:

        ' set up PortalComp - context
    
        Dim MyProjectInfo As New clsProjectInfo
    
        With btn.Attributes
            MyProjectInfo.PortalComp = .Item("PortalComp")
            MyProjectInfo.ContactID = NzN(.Item("ContactNameID"), .Item("BillOrderBy"))
            MyProjectInfo.ContactGeneralID = .Item("ContactGeneralID")
            MyProjectInfo.QuoteNum = .Item("QuoteNum")
            MyProjectInfo.ProjectHeaderID = .Item("ProjectHeaderID")
        End With
        Session("MyProjectInfo") = MyProjectInfo
        Response.Redirect("ProjectUpload", False)
    

    所以我们将带有值的类对象加载到 session() 中。

    现在,在目标页面中,在加载时,我这样做:

       If IsPostBack = False Then
    
         ' copy project info to local view state
         ViewState("Pinfo") = Session("Pinfo")
         cPinfo = Session("Info")   ' form level instances
       Else
            cPinfo = ViewState("Pinfo")
       End if
    

    所以,现在,我有可用于任何和所有代码的类 cPinfo,以及此网页上的所有代码事件。

    因此,您在 vb.net、c# 以及桌面程序或 Web 中使用类的方式非常相似。唯一真正的问题是您必须保留这些值,因为所有网页都被认为是无状态的。这意味着网页被渲染,发送到客户端浏览器,现在服务器端页面实例不再存在!!! - 它被扔掉了 - 超出了范围。因此,每个新的回发都会从 100% 从头开始​​该网页。但是页面上的控件、ViewState 和 session() 都确实存在 - 但您仍然必须考虑到该网页每次使用时都会超出范围 - 它是无状态的。所以所有代码变量只存在于浏览器的回发和往返过程中。一旦后面的代码运行,页面就会被渲染——然后发送回客户端,服务器端页面就消失了——该网页中的所有变量和代码现在都超出了范围——它们消失了!! (除了 ViewState、session(),当然还有该页面上自动支持视图状态的控件(这对您来说是自动完成的 - 所以大多数控件(如文本框、复选框等)都会自动保存它们的状态 - 但不是代码隐藏 -它像子调用一样运行,一旦完成,代码中的所有值都会再次消失并超出范围。

    因此,代码中的变量根本不会在网络中持续存在。

    因此,您需要使用 ViewState 或 session() 在每个用户基础上保存任何值或变量。对于简单的变量,可以使用页面上的隐藏字段。

    因此,仅将 session() 用于对一个用户来说是全局的值,并且如前所述,如果所讨论的值很重要 - 并适用于具有产品 ID 等内容的 ONE 网页,那么您可以仍然使用 session() 来传递值,但是你最好将值从 Session() 快速传输到 ViewState,或该表单上的一些隐藏控件,因为正如我所指出的, session() 对一个用户来说是全局的 - 因此在前几页做出的重要价值观或选择?您可以通过 session() 转移到该目标/下一页,但您最好将任何值从 Session 拉到该页面视图状态,并且如上所述的视图状态是每个用户和每个页面。

    因此,在 asp.net 中需要基本掌握 3 件事

    每个网页(以及类后面的代码)都是无状态的。该页面中的值不存在。请记住,这些网页实际上并不存在于服务器端的内存中 - 它们仅被渲染,代码隐藏运行(修改页面上的控件),页面被发送到客户端浏览器,然后页面被扔掉服务器端!!!

    那些网页是无状态的。尽管启用了视图状态的此类页面上的控件确实会持续存在,但您的 vb.net 值和变量不会。每次用户单击按钮时,您都从头开始。

    最后但并非最不重要的一点 - session() 对每个用户都是全局的,而 Viewstate() 是每个用户每个网页的。

    记住以上所有,你应该没问题。

    【讨论】:

      猜你喜欢
      • 2015-12-17
      • 2015-01-25
      • 2010-09-20
      • 2018-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-10
      相关资源
      最近更新 更多