【问题标题】:How to access the Session in ASP.NET Core via static variable?如何通过静态变量访问 ASP.NET Core 中的 Session?
【发布时间】:2016-10-13 15:17:00
【问题描述】:

在早期版本的 Asp.Net 中,会话可以像使用静态变量一样在任何页面中访问

System.Web.HttpContext.Current.Session["key"]

在 Asp.Net Core 中,如何在通过控制器调用的不同类中访问会话,而不将会话属性作为附加参数传递给所有类的构造函数

【问题讨论】:

  • 阅读文档怎么样? ASP.NET Core现阶段描述的很好:docs.asp.net/en/latest/fundamentals/…
  • 在我在该站点看到的所有示例中,我只能看到“HttpContext objContext”对象作为参数传递给方法/委托,并且会话作为 objContext.Session 访问。我想像早期的 Asp.Net 一样可以使用某种方式,比如 HttpContext.Current.Session ,这样就可以避免传递额外的参数
  • 在控制器内部,您可以访问 HttpContext(如果控制器派生自 Controller 基类),否则您必须注入 IHttpContextAccessor

标签: session asp.net-core asp.net-core-mvc


【解决方案1】:

2017 年 1 月 17 日修订的方法以修复错误

首先,我假设您已将 ASP.NET Core 应用程序配置为使用会话状态。如果没有看到@slfan 的回答How to access the Session in ASP.NET Core via static variable?

如何在通过控制器调用的不同类中访问会话,而不将会话属性作为附加参数传递给所有类的构造函数

Asp.Net Core 是围绕依赖注入设计的,通常设计者没有提供对上下文信息的太多静态访问。更具体地说,没有等同于System.Web.HttpContext.Current

在控制器中,您可以通过this.HttpContext.Session 访问会话变量,但您特别询问了如何通过控制器调用的方法访问会话而不将会话属性作为参数传递。

因此,要做到这一点,我们需要设置自己的静态类来提供对会话的访问,并且我们需要一些代码来在启动时初始化该类。由于一个人可能希望静态访问整个 HttpContext 对象,而不仅仅是 Session,因此我采用了这种方法。

所以首先我们需要静态类:

using Microsoft.AspNetCore.Http; 
using System;
using System.Threading;

namespace App.Web {

    public static class AppHttpContext {
        static IServiceProvider services = null;

        /// <summary>
        /// Provides static access to the framework's services provider
        /// </summary>
        public static IServiceProvider Services {
            get { return services; }
            set {
                if(services != null) {
                    throw new Exception("Can't set once a value has already been set.");
                }
                services = value;
            }
        }

        /// <summary>
        /// Provides static access to the current HttpContext
        /// </summary>
        public static HttpContext Current {
            get {
                IHttpContextAccessor httpContextAccessor = services.GetService(typeof(IHttpContextAccessor)) as IHttpContextAccessor;
                return httpContextAccessor?.HttpContext;
            }
        } 

    }
}

接下来我们需要向 DI 容器添加一个服务,该服务可以提供对当前HttpContext 的访问。此服务随 Core MVC 框架一起提供,但默认情况下未安装。所以我们需要用一行代码“安装”它。此行位于 Startup.cs 文件的 ConfigureServices 方法中,可以位于该方法中的任何位置:

//Add service for accessing current HttpContext
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();    

接下来我们需要设置我们的静态类,以便它可以访问 DI 容器以获取我们刚刚安装的服务。下面的代码位于 Startup.cs 文件的 Configure 方法中。此行可以位于该方法中的任何位置:

AppHttpContext.Services = app.ApplicationServices; 

现在Controller 调用的任何方法,即使是通过异步等待模式,都可以通过AppHttpContext.Current 访问当前的HttpContext

所以,如果我们在Microsoft.AspNetCore.Http 命名空间中使用Session 扩展方法,我们可以将一个名为“Count”的int 保存到会话中,可以这样完成:

AppHttpContext.Current.Session.SetInt32("Count", count);

从会话中检索一个名为“Count”的int 可以这样完成:

int count count = AppHttpContext.Current.Session.GetInt32("Count");

享受。

【讨论】:

  • @Ron C 很好的答案。给其他人的通知,在 Core 1.0 中将 await next(); 替换为 await next.Invoke();
【解决方案2】:

在 Startup.ConfigureServices 你必须添加服务

services.AddSession();

并且在方法配置中你必须使用它(重要:在app.UseMvc()之前调用)

app.UseSession();

现在您可以在控制器中使用它(如果从控制器派生)。你可以存储

var data = new byte[] { 1, 2, 3, 4 };
HttpContext.Session.Set("key", data); // store byte array

byte[] readData;
HttpContext.Session.TryGetValue("key", out readData); // read from session

当您导入命名空间Microsoft.AspNetCore.Http 时,您也可以使用SetStringSetInt32

using Microsoft.AspNetCore.Http;

HttpContext.Session.SetString("test", "data as string"); // store string
HttpContext.Session.SetInt32("number", 4711); // store int

int ? number = HttpContext.Session.GetInt32("number");

在控制器之外,您无权访问 HttpContext,但您可以注入 IHttpContextAccessor 实例,如 answer 中所述

【讨论】:

  • 不知道data byte[]的大小应该怎么办?
  • @user8128167 不知道字节数组的大小是什么意思?在 .NET 中,数据数组的大小始终是已知的。还是我误解了你的问题?
  • 我的意思是如果我要调用 "HttpContext.Session.TryGetValue("key", out data);"那么我不应该知道数据需要的字节大小才能根据“键”从会话中获取值吗?
  • @user8128167 不,因为'data'是一个输出参数,字节数组将被分配。如果您必须事先知道存储数据的大小,那将是相当愚蠢的。您通常在不同的控制器/操作中读取会话日期。
  • 好点,我完全错过了“out”关键字,所以谢谢。如果你把 var data = new byte[] {};而不是“var data = new byte[] { 1, 2, 3, 4 };”?
【解决方案3】:

如果您想从 Session 中存储和检索复杂对象,您可以改用以下扩展:

public static class SessionExtensions
{
    public static void SetObjectAsJson(this ISession session, string key, object value)
    {
        session.SetString(key, JsonConvert.SerializeObject(value));
    }

    public static T GetObjectFromJson<T>(this ISession session, string key)
    {
        var data = session.GetString(key);  
        if (data == null)  
        {  
            return default(T);  
        }  
        return JsonConvert.DeserializeObject<T>(data);
    }
}

然后你会这样称呼他们:

User user = new User();  
user.Name = "Jignesh Trivedi";  
user.Percentage = 75.45;             

HttpContext.Session.SetComplexData("UserData", user); 

或者,

ViewBag.data = HttpContext.Session.GetComplexData<User>("UserData");  

详情请见https://www.c-sharpcorner.com/article/session-state-in-asp-net-core/

【讨论】:

    猜你喜欢
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-01
    相关资源
    最近更新 更多