关于c#:如何从ASP.NET中的任何类访问会话变量?

How to access session variables from any class in ASP.NET?

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

1
Session["loginId"]

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

1
Session["loginId"]

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


(为完整性而更新)
您可以使用Session["loginId"]从任何页面或控件访问会话变量,也可以使用System.Web.HttpContext.Current.Session["loginId"].从任何类(例如,从类库中)访问会话变量

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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会话中存储自身的一个实例,并允许您以类型安全的方式从任何类访问会话属性,例如:

1
2
3
4
5
6
7
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 doc注释来记录会话项
  • 您可以使用默认值初始化会话变量(例如,确保它们不为空)


通过线程HttpContext访问Session: -

1
HttpContext.Current.Session["loginId"]


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


我之前提出的答案提供了解决问题的方法,但是,我觉得理解为什么会出现这个错误很重要:

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

MSDN解释了这是如何可能的:

Because ASP.NET pages contain a default reference to the System.Web namespace (which contains the HttpContext class), you can reference the members of HttpContext on an .aspx page without the fully qualified class reference to HttpContext.

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

我对这种经常遇到的场景的解决方案是我从不将页面对象传递给类。我宁愿从页面Session中提取所需的对象,并以名称 - 值集合/ Array / List的形式将它们传递给Class,具体取决于具体情况。


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

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


在asp.net核心中,这种方式不同:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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/


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

将以下类添加到Web项目中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/// <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);
    }
}

}

这是实施:

1
SessionCentralized.WhatEverSessionVariableYouWantToHold = id;