有没有办法在asp.net核心中使用会话,就像在Web表单中一样?

问题描述 投票:0回答:4

我有一个Web表单项目,我正在尝试将其转换为asp.net核心。我的问题是,在Web表单中,我将一个对象保存到会话中,当我得到它时,我可以对它进行更改并保留它们。另一方面,在核心中,我通过序列化将对象设置为会话。当我得到它并进行更改时,它不会影响会话中存储的对象。有没有办法保存对象(没有序列化),所以当我从会话中获取并对其进行更改时,继续使用它并且不必再次在会话中设置它?

会议是

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

并成功了

AppHttpContext.Current.Session.GetString("object") 

然后我将它反序列化为我想要的对象。

Ps:我使用AppHttpContext来获取控制器之外的会话

c# session asp.net-core httpcontext
4个回答
0
投票

要在会话中使用对象/数组,您需要进行一些自定义:`

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

public static T GetObject<T>(this ISession session, string key)
{
    var value = session.GetString(key);
    return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
} }

现在你可以这样设置:

var objComplex = new ComplexClass();
HttpContext.Session.SetObject("ComplexObject", objNew);

并检索它:

var objComplex = HttpContext.Session.GetObject("ComplexObject");

1
投票

从技术上讲,ASP.NET也从不支持这一点。由于会话存储在这种情况下的工作方式,在使用InProc(即在内存中)会话时恰好发生了侥幸。如果您使用了像SQL Server这样的备用会话存储,则还必须在会话内外对序列化/反序列化对象。 ASP.NET Core的不同之处仅在于使用通用会话存储,因此即使您使用的是内存存储,它也会强制对任何对象进行序列化/反序列化。

也就是说,你的问题是你根本就没有坚持你的改变。再一次,你依赖于意外行为。因为ASP.NET直接将对象保存在内存中,所以对该对象执行操作会自动“持久化”,因为它是相同的引用。在反序列化时,您正在创建一个新实例,因此除非您在之后将对象序列化回会话,否则操作将不会持续存在。

最后,Web Forms还是不,这从来都不是推荐的甚至是正确的做事方式。会话存储是不稳定的。它不适用于除短期(和不可靠)持久性之外的任何事情。换句话说,你永远不能指望会话中的某些东西,所以你应该总是在数据不存在的情况下进行防御性编码。如果你依赖于存在的东西,就像这里的情况一样,那么你总是让自己陷入失败之中。

但是,如果你正在做类似多步形式的事情,那么进入会话的各个步骤是可以接受的,尽管你实际上应该使用TempData而不是Session。但是,在最后一步,您的组合对象应该保存在SQL Server之类的内容中,而不是会话中。在几乎所有其他情况下,您应该只是坚持像SQL Server这样的东西,并完全避免使用Session


0
投票

ASP.NET核心不支持将对象直接保存到Session中,就像Web窗体项目一样。在ASP.NET Cpre中,只有直接支持将基本类型保存到Session中,如stringintbyte数组。因此,任何更复杂的对象都需要序列化为字符串或直接序列化为字节数组,然后该序列化可以存储在Session中。

人们通过对对象进行JSON序列化来生成字符串然后将字符串保存到Session来实现这一点很常见。但是当您从Session检索JSON字符串并将其反序列化为对象时,对该对象的任何更改都不会反映在表示当前存储在会话中的对象的先前JSON中。所以对象的变化并没有直接反映在Session中。

这与Web窗体中看到的行为非常不同,并且由于对象未存储在会话中,因此序列化就是这样。因此,如果您更改对象并希望将这些更改存储在会话中,则需要再次序列化该对象并将该序列化(例如json)存储在会话中。

这有帮助吗?


0
投票

迁移任务不是直截了当的。

您可以按照以下步骤操作:

1)首先替换您对可以注入控制器或其他服务的某种服务的Session的依赖性。一个好主意是在此服务中硬编码值,以检查是否所有代码都取决于您之前的会话实现是否能够使用新服务。

2)实现一个过滤器(例如通过在Razor页面的情况下实现IAsyncPageFilter)来接入HttpContext用户并设置某种可以从Cache实现中检索的Lookup对象 - 一个好主意是使用Redis分布式缓存。此对象应具有Key作为用户标识 - 值可以是您可能要添加到“会话”的任何数据。使用“缓存”服务来实现此目的,从客户端代码中隐藏缓存实现细节。 (请记住使这些“请求”范围依赖关系,以便适当填充HttpContext用户。)

3)在新服务上实现方法以添加/修改Cache对象以保持“会话”数据的更新。

故事的道德:减少对平台特定功能的依赖。至少使用某种服务封装这些依赖项,这些服务可以在以后根据这些功能在没有客户端代码的情况下替换。

© www.soinside.com 2019 - 2024. All rights reserved.