如何从ASP.NET中的任何类访问会话变量?


157

我在应用程序的App_Code文件夹中创建了一个类文件。我有一个会话变量

Session["loginId"]

我想在我的班级中访问此会话变量,但是当我编写以下行时,它给出了错误

Session["loginId"]

谁能告诉我如何访问在ASP.NET 2.0(C#)的app_code文件夹中创建的类中的会话变量

Answers:


363

(为了完整性起见,已更新)
您可以使用Session["loginId"]以及从任何类(例如,从类库内部)使用来访问任何页面或控件中的会话变量System.Web.HttpContext.Current.Session["loginId"].

但请继续阅读我的原始答案...


我总是在ASP.NET会话周围使用包装器类,以简化对会话变量的访问:

public class MySession
{
    // private constructor
    private MySession()
    {
      Property1 = "default value";
    }

    // Gets the current session.
    public static MySession Current
    {
      get
      {
        MySession session =
          (MySession)HttpContext.Current.Session["__MySession__"];
        if (session == null)
        {
          session = new MySession();
          HttpContext.Current.Session["__MySession__"] = session;
        }
        return session;
      }
    }

    // **** add your session properties here, e.g like this:
    public string Property1 { get; set; }
    public DateTime MyDate { get; set; }
    public int LoginId { get; set; }
}

此类在ASP.NET会话中存储自身的一个实例,并允许您从任何类中以类型安全的方式访问会话属性,例如:

int loginId = MySession.Current.LoginId;

string property1 = MySession.Current.Property1;
MySession.Current.Property1 = newValue;

DateTime myDate = MySession.Current.MyDate;
MySession.Current.MyDate = DateTime.Now;

这种方法有几个优点:

  • 它使您免于大量类型转换
  • 您不必在整个应用程序中都使用硬编码的会话密钥(例如Session [“ loginId”]
  • 您可以通过在MySession的属性上添加XML文档注释来记录会话项目
  • 您可以使用默认值初始化会话变量(例如,确保它们不为空)

6
无需编写任何代码,如答案所示使用。例如“ public int LoginId {get; set;}”->这称为自动属性。
M4N

4
如果您使用的是.net 3.x,则可以使用代码中显示的自动属性。对于.net 2.x / 1.x,此功能不可用,您必须自己实现属性的getter / setter:private int _loginId; public int LoginId {get {return _loginId; }设置{_loginId =值;}
M4N

2
现在看起来很酷,我想我已经解决了我的问题,现在我正在使用您的方式,它非常干净并且易于将我所有的会话变量保存在一个地方。谢谢@马丁,您真棒。
Prashant

23
@ M4N,希望我能表达的感谢多于+1。这已成为我在项目中处理会话/缓存的最喜欢的方式。从字面上看,我的代码感谢您。
布兰登·布恩

4
@Kristopher的“ Current”属性为静态时,返回的MySession实例不是...所以很好。静态方法和属性可以通过这种方式安全使用。
达伦(Darren)

104

通过线程HttpContext访问会话:

HttpContext.Current.Session["loginId"]

非常感谢Anthony所做的这一简单步骤。
Kings

非常感谢安东尼,为此+1
Owais Qureshi 2012年

谢谢。忘记了名称空间是什么:)
安东尼·霍恩

@AnthonyWJones我使用了您的方法,但有问题,您能解释一下我的问题所在或正确的使用方式是我的问题stackoverflow.com/questions/45254279/…–
adnan

如果要转换为HttpSessionStateBase,则:HttpSessionStateBase session = new HttpSessionStateWrapper(HttpContext.Current.Session);
回复

24

建议的解决方案存在的问题是,如果您使用进程外会话存储,则会破坏SessionState内置的某些性能功能。(“状态服务器模式”或“ SQL Server模式”)。在oop模式下,会话数据需要在页面请求的末尾进行序列化,并在页面请求的开始进行反序列化,这可能会导致开销很大。为了提高性能,SessionState尝试仅对第一次访问时仅反序列化的变量进行反序列化,并且仅重新序列化并替换已更改的变量。如果您有很多会话变量并将它们全部推入一个类,则实际上,在使用该会话的每个页面请求中,会话中的所有内容都会反序列化,并且即使仅更改了一个属性(因为该类已更改),所有内容都需要再次序列化。如果您使用大量会话和oop模式,则只需考虑一下。


4
+1可以激发灵感。如果您没有使用InProc for Session,那么Ernie是100%正确的。无论如何,InProc非常有限,因为它不支持Webfarms,如果重新启动应用程序,它将丢失。请注意,根据性能成本,我们认为使用State Server模式的成本要高出20%,并且在此基础上还要增加序列化成本。您可以想象,这会变得昂贵。您可以通过坚持原始类型(例如,int,字符串,char,byte等)来避免一些序列化开销。自定义对象将面临序列化。用户当心。
扎克·詹森

+1好点。将这两个概念结合起来的更改将是使此自定义“会话”类上的每个属性都调用asp.net会话本身,而不是会话中的一个大对象。必须进行@ M4N的方法避免的类型转换,但是如果您每次仅读取一些会话,则可能值得这样做。
eol 2013年

12

我面前提出的答案为该问题提供了适当的解决方案,但是,我认为了解此错误的原因很重要:

所述Session的属性Page返回类型的实例HttpSessionState相对于该特定的请求。Page.Session实际上等同于调用Page.Context.Session

MSDN解释了这是怎么可能的:

由于ASP.NET页包含对System.Web命名空间的默认引用(包含HttpContext类),因此您可以HttpContext在.aspx页上引用成员,而无需完全限定类引用HttpContext

但是,当您尝试在App_Code的类中访问此属性时,该属性将对您不可用,除非您的类是从Page Class派生的。

我对这种经常遇到的情况的解决方案是,我永远不会将页面对象传递给class。我宁愿从Session页面提取所需的对象,并根据情况将它们以名称-值集合/数组/列表的形式传递给Class。


很好的解释,它帮助我+1 :)
Owais Qureshi 2012年

1

我遇到了同样的错误,因为我试图在自定义Session类中操纵会话变量。

我必须将当前上下文(system.web.httpcontext.current)传递给该类,然后一切正常。


1

在asp.net核心中,这有不同的工作方式:

public class SomeOtherClass
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private ISession _session => _httpContextAccessor.HttpContext.Session;

    public SomeOtherClass(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public void TestSet()
    {
        _session.SetString("Test", "Ben Rules!");
    }

    public void TestGet()
    {
        var message = _session.GetString("Test");
    }
}

资料来源:https : //benjii.me/2016/07/using-sessions-and-httpcontext-in-aspnetcore-and-mvc-core/


0

这对于应用程序和开发人员来说都应该更加有效。

将以下类添加到您的Web项目:

/// <summary>
/// This holds all of the session variables for the site.
/// </summary>
public class SessionCentralized
{
protected internal static void Save<T>(string sessionName, T value)
{
    HttpContext.Current.Session[sessionName] = value;
}

protected internal static T Get<T>(string sessionName)
{
    return (T)HttpContext.Current.Session[sessionName];
}

public static int? WhatEverSessionVariableYouWantToHold
{
    get
    {
        return Get<int?>(nameof(WhatEverSessionVariableYouWantToHold));
    }
    set
    {
        Save(nameof(WhatEverSessionVariableYouWantToHold), value);
    }
}

}

这是实现:

SessionCentralized.WhatEverSessionVariableYouWantToHold = id;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.