Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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]

like image 571
Martin Avatar asked Dec 08 '16 18:12

Martin


1 Answers

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

like image 132
Paul Bruce Avatar answered Oct 20 '22 00:10

Paul Bruce