我有一个Web表单项目,并且正在尝试将其转换为asp.net核心。我的问题是,在Web表单中,我将一个对象保存到会话中,当我获取该对象时,可以对其进行更改并将其保留。另一方面,在内核中,我通过序列化将对象设置为会话。当我获取并进行更改时,它不会影响会话中存储的对象。有没有一种方法可以保存对象(不进行序列化),因此当我从会话中获取对象并对其进行更改时,可以继续使用它,而不必在会话中再次设置它?
会议是
System.Web.HttpContext.Current.Session["object"]
做到了
AppHttpContext.Current.Session.GetString("object")
然后我将其反序列化为我想要的对象。
Ps:我使用AppHttpContext在控制器之外获取会话
答案 0 :(得分:0)
ASP.NET核心不支持Web窗体项目可以将对象直接保存到Session
中。在ASP.NET Cpre中,仅直接支持将原始类型保存到Session
,string
或int
数组等byte
中。因此,任何更复杂的对象都需要序列化为字符串或直接序列化为字节数组,然后可以将序列化存储在Session
中。
人们通常通过对对象进行JSON序列化以生成字符串,然后将字符串保存到Session
中来完成此操作。但是,当您从Session
中检索JSON字符串并将其反序列化为一个对象时,对该对象的任何更改都不会反映在表示当前存储在会话中的对象的先前JSON中。因此,对对象的更改不会直接反映在Session
中。
这与Web窗体中的行为截然不同,其原因是对象没有存储在会话中,而是序列化的。因此,如果您更改对象并希望将这些更改存储在会话中,则需要再次序列化对象,并将该序列化(例如json)存储在会话中。
有帮助吗?
答案 1 :(得分:0)
从技术上讲,ASP.NET也从不支持此功能。由于在这种情况下会话存储的工作方式,因此在使用InProc(即在内存中)会话时碰巧是偶然的。如果使用备用会话存储(如SQL Server),则还必须在会话中进行对象的序列化/反序列化。 ASP.NET Core的不同之处仅在于使用通用会话存储,因此即使您使用的是内存存储,它也会强制对任何对象进行序列化/反序列化。
也就是说,这里的问题是您根本没有将更改保留下来。同样,您是依靠意外行为。因为ASP.NET直接将对象持久存储在内存中,所以对对象执行的操作会自动“持久化”,因为它是相同的引用。反序列化时,您正在创建一个新实例,因此除非将对象随后序列化回会话中,否则操作将不会持续。
最后还是Web窗体,否,这从来都不是建议或正确的做事方式。会话存储是易失的。除了短期(和不可靠)持久性之外,它不用于其他任何目的。换句话说,您永远不能指望会话中存在某些内容,因此您应该始终在数据不存在的情况下进行防御性编码。如果您要依靠那里的东西,听起来像是这里的情况,那么您总是会为失败做好准备。
但是,如果您正在执行类似多步骤表单的操作,则可以将各个步骤都加入到会话中,尽管您应该实际上使用TempData
而不是Session
。但是,在最后一步,应将组成的对象持久保存在类似SQL Server的环境中,而不是会话中。在几乎所有其他情况下,您都应该坚持使用SQL Server之类的东西,而完全避免使用Session
。
答案 2 :(得分:0)
迁移任务将不会很简单。
您可以按照以下步骤操作:
1)首先,替换对Session的依赖,这种依赖可以注入到控制器或其他服务中。一个好主意是对该服务中的值进行硬编码,以检查所有代码(取决于您先前的会话实现)是否能够使用新服务。
2)实现一个过滤器(例如,在Razor页面的情况下,通过实现IAsyncPageFilter)以进入HttpContext用户并设置某种可以从Cache实现中检索的Lookup对象-一个好主意是使用Redis分布式缓存。该对象应具有Key作为用户身份-值可以是您可能要添加到“会话”的任何数据。使用“缓存”服务来实现此目的,并从客户端代码中隐藏缓存的实现细节。 (请记住要使这些“请求”作用域具有依赖性,以便适当地填充HttpContext用户。)
3)在新服务上实现方法,以添加/修改Cache对象,以使“会话”数据保持更新。
故事的寓意:减少对平台特定功能的依赖。至少使用某种服务来封装这些依赖关系,这些服务以后可以替换,而无需依赖这些功能的客户端代码。
答案 3 :(得分: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");