【问题标题】:Accessing public class variables in asp.net without session在没有会话的情况下访问 asp.net 中的公共类变量
【发布时间】:2012-02-15 18:18:18
【问题描述】:

我正在使用我发现的这个示例来学习如何加载类文件并通过它们访问变量。这是在 App_Code 文件夹中名为 Class1.vb 的文件中(这不是应用程序项目):

Imports Microsoft.VisualBasic
Public Class my_class
    Public Shared Sub my_sub()
        Dim vartest As String
        vartest = 10
        HttpContext.Current.Session("myvar") = vartest
    End Sub
End Class

这是 aspx 文件的代码隐藏:

    Imports my_class
Partial Public Class test
    Inherits System.Web.UI.Page
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        my_class.my_sub()
        Label1.Text = HttpContext.Current.Session("myvar")
    End Sub
End Class

如何在不使用会话的情况下访问 vartest 变量,因为如果多个函数同时访问该变量,我假设该变量可能会被覆盖。是否可以采用另一种方式,将变量发送到类文件?

【问题讨论】:

    标签: asp.net vb.net session


    【解决方案1】:

    听起来您需要快速了解一些基本的 ASP.Net Webforms 概念。首先我要反驳一个常见的新手误解:

    您的 Page 类不会在 Web 服务器上停留很长时间

    我认为许多新的 ASP.Net 开发人员都有这样的想法,即 Web 服务器为访问其站点的每个用户会话保留其页面类的单个实例,并且每个回发或事件都使用相同的页面类实例。这不是它的工作原理。 ASP.Net 页面类实例几乎总是会在不到一秒的时间内再次被创建和销毁,大​​多数有经验的开发人员认为如果需要更长时间,这是一个大问题。

    ASP.NET 依赖于 HTTP 协议

    这里要记住的是 ASP.Net 仍然依赖于 HTTP 协议,而 http 归结为 requestsresponses。当您查看网页时,您的浏览器首先会向服务器发送一个请求。服务器响应,通常使用 html 文档。然后浏览器将解析 html;根据它在 html 中看到的内容,浏览器可能会向服务器发送更多请求,以获取更多资源,例如 javascript、图像或 css 文件。每个请求都会产生一个单独的响应,浏览器使用所有这些资源将页面呈现到屏幕上。然而,ASP.Net 运行时通常不需要处理额外的请求(这会使事情变慢)——只有初始 html 需要 ASP.Net 支持;您希望其他资源是可以缓存的基本文件。

    ASP.Net 运行时为每个请求创建一个新的类实例。

    当 ASP.net 运行时处理对页面的请求时,它将创建页面类的新实例。运行时将遵循ASP.Net Page lifecycle(这应该真正命名为“ASP.Net 页面请求生命周期”),并按照定义的特定顺序调用此类实例中的某些方法或引发某些事件按生命周期。

    这意味着每个回发或事件都在您类的不同实例中运行。

    这也意味着每个回发或事件都在重建和传输 所有 进入您页面的 html,而不仅仅是您想要更改的部分。对于您的服务器代码,结果是类级变量在 ASP.Net 中真正有用的唯一事情就是将在单个 http 请求中使用的事情。对于浏览器,结果是您在每次事件后都使用全新的 DOM

    要理解所有这些,重要的是要很好地理解类和类的实例之间的区别。您问题中的几项让我不确定您是否有这种理解。

    ASP.Net 运行时在您网站的所有用户之间共享一个应用程序实例

    对于整个网站及其所有用户,Web 服务器通常只有一个应用程序实例。因此,任何具有共享/静态范围的东西对每个用户都是通用的。在 ASP.Net 中很少适合共享/静态的任何内容。

    那么您如何处理应该由单个用户保存或访问您的网站的数据?

    正是Session 的用途。在任何给定时间,会话对于单个请求始终是唯一的。您担心多个函数同时访问会话,但这不会发生。 ASP.Net 页面生命周期确保除非您手动生成额外的线程,否则对于给定的 HttpContext 和 Session,一次只运行一个函数。如果用户以某种方式在大约同一时间发送两个应该具有相同 Session/HttpContext 的请求,则一个将由 ASP.Net 运行时保留,直到另一个完成。如果您不想一直引用会话,则可以在类中构建包装会话变量的属性。示例见@Pankaj's answer

    【讨论】:

    • 我想知道,当你说“浏览器将解析 html”时的那一行是什么意思?
    • 当您说“时您不认为两者是矛盾的,并且根据它所看到的可能会向服务器发送更多请求以获取其他资源,例如 javascript、图像或 css 文件。但是,asp.net 运行时通常不必处理这些其他请求(这会使事情变慢)。"
    • @Pankaj - asp.net 运行时是作为 IIS Web 服务器一部分的模块或“处理程序”。 IIS Web 服务器将处理额外的请求,但通常不会调用 asp.net 运行时处理程序(尽管有时人们会将其配置为处理 javascript 或 css)
    • @Pankaj - 你认为“浏览器将解析 html”是什么意思?
    • 了解您对处理程序/Web 服务器的第一条评论...但怀疑是,在网站中,我们通常有图像/css,通常每次都会下载到客户端。您将链接到共享的任何链接,说明句子“并根据它看到的内容可能会向服务器发送更多请求以获取其他资源,例如 javascript、图像或 css 文件”我想要了解背后的机制/细节 - 再次返回服务器以按需获取图像/css...
    【解决方案2】:

    首先,Session 具有用户范围,因此它不会被另一个请求覆盖。

    Is it safe to access asp.net session variables through static properties of a static object?

    您可以将访问封装到一个属性中:

    Public Shared Property MyVar() As String
        Get
            If HttpContext.Current.Session("MyVar") Is Nothing Then
                HttpContext.Current.Session("MyVar") = ""
            End If
            Return DirectCast(HttpContext.Current.Session("MyVar"), String)
        End Get
        Set(value As String)
            HttpContext.Current.Session("MyVar") = value
        End Set
    End Property
    

    那么你可以通过以下方式获取变量:

    Label1.Text = my_class.MyVar
    

    【讨论】:

    • 我的意思是如果类中的同一个函数在一个页面中由同一个人多次运行
    • @sfreelander:那么应该如何同时调用呢?如果您要启动多个读/写此属性的线程,这将不再是线程安全的。但对于每个(非本地)对象都是如此。然后你需要某种锁定机制。 geekswithblogs.net/chrishan/archive/2005/11/04/59102.aspx
    • @sfreelander - 这不可能发生。为每个 http 请求创建一个新的类实例。 ASP.Net 页面类实例几乎总是会在不到一秒的时间内再次被创建和销毁,而且大多数页面开发人员会在他们花费更长的时间时将其视为一个大问题。
    【解决方案3】:

    除了“Tim Schmelter”回复....

    你可以创建一个BaseClass,它将继承自

    System.Web.UI.Page
    

    按照“Tim”的建议放置属性。您需要做的唯一更改是将访问修饰符更改为Protected,您应该删除Public and Shared

    您还可以保留其他常用功能,我们可以在其他类中重用的属性...同样,您也可以为您的用户控件创建 BaseControls

    最后在web表单中继承这个类....

    希望对你有所帮助...

    基类代码

    Imports System
    Imports System.Collections.Generic
    Imports System.Linq
    Imports System.Web
    
    Public Class BaseClass
        Inherits System.Web.UI.Page
        Protected Property MyVar() As String
            Get
                If HttpContext.Current.Session("MyVar") Is Nothing Then
                    HttpContext.Current.Session("MyVar") = ""
                End If
                Return Convert.ToString(HttpContext.Current.Session("MyVar"))
            End Get
            Set
                HttpContext.Current.Session("MyVar") = value
            End Set
        End Property
    End Class
    

    示例代码“隐藏代码” - 显示基类中受保护成员数据的用法

    Imports System
    Imports System.Collections.Generic
    Imports System.Linq
    Imports System.Web
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    
    Public Partial Class Default5
        Inherits BaseClass
        Protected Sub Page_Load(sender As Object, e As EventArgs)
            If Not Page.IsPostBack Then
                Dim str As String = Me.MyVar
            End If
        End Sub
    End Class
    

    【讨论】:

      【解决方案4】:

      通常你可以使用不同的地方来存储应用程序状态:Application(应用程序范围,将状态保存到应用程序域中),Session(可以保存当前浏览器会话将访问的所有内容),ViewState(存储在隐藏输入中的变量字段并将在每次回发时发布)。当然,您也可以将状态保存到数据库或文件中。我不确定你想要实现什么,但看起来你正在寻找 ViewState 之类的东西。

      阅读ASP.NET State Management

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-20
        • 2014-03-04
        • 1970-01-01
        • 2016-05-14
        • 1970-01-01
        • 2012-10-13
        • 1970-01-01
        • 2014-11-09
        相关资源
        最近更新 更多