HttpContext.Current.Session in a Shared method isn't persisting changes
Asked Answered
A

2

6

I'm using some WebMethods in a System.Web.UI.Page to handle some ajax requests, and I'm trying to store an object in the session to retain information across several ajax requests and even after leaving the page and returning.

I'm accessing the session through HttpContext.Current.Session("foo"), and if it's Nothing, I set it via HttpContext.Current.Session("foo") = New Bar().

The problem I'm running into is that after it gets set, next time I hit that method it has been reset. I tried changing some other session variables that are set elsewhere and they get reverted too. This tells me that I'm getting a copy of the session state, rather than a reference which I can update and cause to persist from request to request. I double-checked that the EnableSession property of WebMethod is True, but still changes to session state are not kept.

Method declaration:

<System.Web.Services.WebMethod(EnableSession:=True)>
Public Shared Function foo(ByVal woNum As String, ByVal workCenter as String) As ToolingModel
    Return ToolingModel.getSessionTooling(woNum, workCenter)
End Function

getSessionTooling:

Public Shared Function getSessionTooling(woNum As String, workCenter As String) As ToolingModel
    Dim tooling As ToolingModel = HttpContext.Current.Session(TOOLING_MODEL_SESSION_KEY)

    If tooling Is Nothing Then
        tooling = New ToolingModel(woNum, workCenter)
        HttpContext.Current.Session(TOOLING_MODEL_SESSION_KEY) = tooling
    ElseIf tooling.woNum <> woNum OrElse tooling.workCenter <> workCenter Then
        tooling.woNum = woNum
        tooling.workCenter = workCenter
        tooling.assets.Clear()
    End If

    Return tooling
End Function

How can I get my changes to apply to the persistent session state, accessing it from a Shared WebMethod?

Edit: found my problem, a week too late. Line 1 of the .aspx:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="foo.aspx.vb" 
    Inherits="foo" MaintainScrollPositionOnPostback="true" 
    MasterPageFile="~/mstrFoot.master" EnableSessionState="ReadOnly" %>

The page was set to have a read-only session, which overrides the PageMethod's EnableSession setting. [facepalm]

Ankle answered 8/12, 2016 at 18:31 Comment(4)
can you post the function declaration as well? looks like it should work if you add the correct attribute: #4759075 [WebMethod(EnableSession = true)]Amaris
Could it be a configuration issue? Maybe an issue with POST vs GET? When users log in we set a bunch of session variables and they persist just fine, but I can't get changes to the session to persist if I do them here.Ankle
what versions of .net are you working with, just so I can more accurately test this?Amaris
This solved my issueBolingbroke
S
1

IIS will by default take advantage of a multi-core CPU. In a multi-processor environment, the default InProc SessionState setting in the web.config randomly processes requests on different threads (separate threads per processor/core). More detail here: https://msdn.microsoft.com/en-us/library/ms998549.aspx#scalenetchapt06_topic8

FYI, though I have also done this myself in the past, maintaining session state between requests to a Web API (SOAP/REST) is frowned on because it represents server overhead that is hard to scale. Storing complex objects in session state also requires every aspect of that object/properties/fields to be serializable too, which can get very tricky. That said...

Based on the information you provided, you need to set up your web app to use the StateServer mode AND enable the ASP.NET State Service on some machine so that multiple requests handled by separate threads will maintain the session across CPUs. https://msdn.microsoft.com/en-us/library/ms178586.aspx

Sailboat answered 19/12, 2016 at 14:35 Comment(2)
SessionState is currently set to SQLServer mode, does this accomplish the same as StateServer?Ankle
If you have verified that sessions are getting persisted to SQL server, then yes, this accomplishes the same thing as StateServer. You may also have to implement custom Serialization for your custom object. Read the 'out-of-proc' session of this article to make sure your custom object will be serialized/deserialized properly: hanselman.com/blog/…Sailboat
P
1

If your session is not timing out, the most likely reason is that ASP.NET is generating a different sessionID between your webmethod requests and your (aspx?) page calls. You likely have the same session available (if not timed out and cookies enabled) between two web method calls but not across the page call and the webmethod.

Cannot get session in webmethod in asp.net

Palmerpalmerston answered 19/12, 2016 at 15:2 Comment(5)
I can get session variables out of the session (e.g. user's name, email address, etc.) which were set elsewhere in the app, but anything I change in the WebMethod doesn't stick around.Ankle
Where is getSessionTooling defined? You're not passing the httpcontext to that method, it's likely not getting the correct httpcontext for the request. Try passing the context into the method call.Palmerpalmerston
It's defined in my ToolingModel class. I did try passing in the Session from the WebMethod, but I had the same problem with the session not retaining changes.Ankle
Did you check the link i posted? Verifying that you have the same Session ID between different requests?Palmerpalmerston
I just checked, I get the same session id between different requests, even across different pages and WebMethod vs Page_Load.Ankle

© 2022 - 2024 — McMap. All rights reserved.