C# .Net Web - Session Variable Not Persisting

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • ltarrant
    New Member
    • Mar 2008
    • 3

    C# .Net Web - Session Variable Not Persisting

    Hi, I'm having problems with a DataTable I'm storing in a session variable. I use this as a temporary store for a shopping cart until a customer goes through the checkout and the cart is saved to my database.

    I have used DataTables stored in sessions before for shopping baskets with no problems. However, on this occasion I am only passing the AddHandler the product id and the quantity being added. The Handler then calls a getProductDetai l method to lookup the product name & price from the database. The handler then passes these details to the AddToDataTable method to add a new row to the DataTable stored in the session.

    For some reason the process of retrieving data from the database seems to be killing the session variable. Meaning everytime I add an item to the DataTable the previous item(s) already in the basket are lost and only the most recent item added appears.

    I can't for the life of me figure out what is wrong. If I call the AddToDataTable method directly then everything works fine and multiple rows can be added to the TempBasket.

    Here my code. Hopefullly someone can point out some stupid mistake I have made. I really need to get this working ASAP as I'm working to a deadline.

    Code:
    <%@ Page Language="C#" Debug="true" %>
    <%@ import Namespace="System" %>
    <%@ import Namespace="System.Data" %>
    <%@ import Namespace="System.Data.OleDb" %>
    
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    
    <script runat="server">
      
        void bindTempBasket()
        {
            DataTable dtTempBasket = mGetTempBasket();
    
            dgDebugTableDisplay.DataSource = dtTempBasket;
            dgDebugTableDisplay.DataBind();
        }
    
        public DataTable mGetDataTable(string sSQL)
        {
            string sCString = ConfigurationSettings.AppSettings["ConnectionString"];
            using (OleDbConnection myConnection = new OleDbConnection(sCString))
            {
                OleDbCommand myCommand = new OleDbCommand(sSQL, myConnection);
                OleDbDataAdapter myAdapter = new OleDbDataAdapter(myCommand);
                DataTable dtTable = new DataTable("Table");
                myAdapter.Fill(dtTable);
                
                return dtTable;
            }
            
        } //End mGetDataTable method
    
    
        public DataTable mGetProductDetails(int iID)
        {
            string sSQL = "SELECT PVariant_ID, Product_Name, Product_TradeCost FROM qryProductList WHERE PVariant_ID = " + iID + ";";
            DataTable dtProductDetails = mGetDataTable(sSQL);
    
            return dtProductDetails;
        } //End mGetProductDetails method
    
    
        public DataTable mCreateTempBasketTable()
        {
            DataTable myTable = new DataTable("Basket");
            DataColumn dtCol;
    
            dtCol = new DataColumn();
            dtCol.DataType = System.Type.GetType("System.Int32");
            dtCol.ColumnName = "PVariant_ID";
            myTable.Columns.Add(dtCol);
    
            dtCol = new DataColumn();
            dtCol.DataType = System.Type.GetType("System.String");
            dtCol.ColumnName = "Product_Name";
            myTable.Columns.Add(dtCol);
    
            dtCol = new DataColumn();
            dtCol.DataType = System.Type.GetType("System.Int32");
            dtCol.ColumnName = "IOrderLine_Quantity";
            myTable.Columns.Add(dtCol);
    
            dtCol = new DataColumn();
            dtCol.DataType = System.Type.GetType("System.Double");
            dtCol.ColumnName = "IOrderLine_UnitCost";
            myTable.Columns.Add(dtCol);
    
            DataColumn[] myPrimaryKeyColumns = new DataColumn[1];
            myPrimaryKeyColumns[0] = myTable.Columns["PVariant_ID"];
            myTable.PrimaryKey = myPrimaryKeyColumns;
    
            return myTable;
        }//End createBasketTable Method
    
        public DataTable mGetTempBasket()
        {
            if (Session["basket"] == null)
            {
                DataTable dtBasket = mCreateTempBasketTable();
                Session["basket"] = dtBasket;
            }
            return (DataTable)Session["basket"];
        }//End mGetBasket Menthod
    
        public void mSaveTempBasket(DataTable newTable)
        {
            Session["basket"] = newTable;
        }
    
        void mAddHandler(int iID, int iQuantity)
        {
            DataTable dtProductDetail = mGetProductDetails(iID);
    
            if (dtProductDetail.Rows.Count > 0)
            {
                int iPVariant_ID = Convert.ToInt32(dtProductDetail.Rows[0]["PVariant_ID"]);
                string sProduct_Name = Convert.ToString(dtProductDetail.Rows[0]["Product_Name"]);
                double dUnitCost = Convert.ToDouble(dtProductDetail.Rows[0]["Product_TradeCost"]);
    
                mAddToDataTable(iPVariant_ID, sProduct_Name, iQuantity, dUnitCost);
            }
        }
    
        void mAddToDataTable(int iID, string sProductName, int iQuantity, double dUnitCost)
        {
            DataTable dtBasket = mGetTempBasket();
            DataRow dtRow;
            dtRow = dtBasket.NewRow();
            dtRow["PVariant_ID"] = iID;
            dtRow["Product_Name"] = sProductName;
            dtRow["IOrderLine_Quantity"] = iQuantity;
            dtRow["IOrderLine_UnitCost"] = dUnitCost;
            dtBasket.Rows.Add(dtRow);
    
            mSaveTempBasket(dtBasket);
        }
    
        void AddItem_Click(object sender, EventArgs e)
        {
            //Temp method for debug
            
            int iID = Convert.ToInt32(ItemCode.Text);
    
            //mAddToDataTable(iID, "Test Product Name", 1, "", 99.99);
    
            mAddHandler(iID, 1);
    
            bindTempBasket();
        }
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Product Search</title>
        <link rel="Stylesheet" href="CSS/default.css" />
    </head>
    <body>
        <form id="form1" runat="server">
             
        <asp:TextBox ID="ItemCode" runat="server"></asp:TextBox>
            <asp:Button ID="AddItem"
            runat="server" Text="Button" onclick="AddItem_Click" />
    <asp:datagrid id="dgDebugTableDisplay" runat="server" />
    
    
        </form>
    </body>
    </html>
    I am happy to upload the backend access database this page uses if someone wants to test the code.

    Thanks in advance for any help that can offered.
  • Plater
    Recognized Expert Expert
    • Apr 2007
    • 7872

    #2
    I would wonder if you could print out the session ID to the page (for debug purposes) and see if it ever changes.
    That is what it is sounding like to me, that for some reason your browser is not correctly maintaining the session cookie id, and thus everytime you load, a new session id is generated?

    Comment

    • ltarrant
      New Member
      • Mar 2008
      • 3

      #3
      Hi Plater, what do you mean by print out the Session ID? How would I do that?

      What ever the problem it happens in both IE and FF on 4 different computers I've tried.

      I have been using the VS2008 built in test server. After I couldnt get it to work their I tried uploading it to our webserver to test if it was some problem with VS2008 losing the session. It worked on the server for an hour and then stopped working their as well, even though I hadn't changed the file?

      Very strange!

      Ideally I'd like to fix the code I have but if there is some other method of temporily storing the datatable I'd try it. I'd like to avoid storing the temp basket in the database though.

      Comment

      • Plater
        Recognized Expert Expert
        • Apr 2007
        • 7872

        #4
        Are you using the default Session style (and not trying to use a SQL server instance for Session State)?
        Is there anywhere where you are Abandon()'ing the Session?
        Is it even possible to string-serialize the DataTable object with Data in it?

        Session.LCID returns the unique Session ID that gets passed around.
        Session.IsNewSe ssion will tell you if this page load is of a new session.

        Comment

        • ltarrant
          New Member
          • Mar 2008
          • 3

          #5
          I am using the default session variable and I am not abandoning the session at any point.

          I tried using ViewState instead of a Session which worked on the first page. But the problem is I need to use the DataTable on a second page (popup) and can't access the ViewState on the opener page.

          I tried just using a Session briefly to take the content of the ViewState["TempBasket "] and pass it to the ViewState on the popup page. This made everything work for a bried period but not it stopped working again.

          It driving me insane. Is there some other way to store a DataTable but also allows it to be passed between pages?

          Comment

          • balabaster
            Recognized Expert Contributor
            • Mar 2007
            • 798

            #6
            It almost sounds like you want to restructure your site slightly. Use master pages, store your basket in the master frame and then use content pages to update and manage the basket. Should bypass the issue of needing to pass the basket between pages.

            Comment

            • Plater
              Recognized Expert Expert
              • Apr 2007
              • 7872

              #7
              I had no trouble making a DataTable persist through Session?

              I put this on my default page.
              Code:
              DataTable tempdt;
              if (Session["temptable"] == null)
              {
              	tempdt = new DataTable("Barny");
              	tempdt.Columns.Add("Page");
              	tempdt.Columns.Add("Hits");
              	DataRow dr = tempdt.NewRow();
              	dr["Page"] = "Default";
              	dr["Hits"] = 1;
              	tempdt.Rows.Add(dr);
              	Session.Add("temptable", tempdt);
              }
              else
              {
              	tempdt = (DataTable)Session["temptable"];
              	foreach (DataRow d in tempdt.Select("Page='Default'"))
              	{
              		int h = int.Parse(d["Hits"].ToString());
              		h++;
              		d["Hits"] = h;
              		Session["temptable"] = tempdt;
              	}
              }
              Everytime the page is loaded it will increment (or create if first time) a value and then update it in the object.
              Then on a different page I have it displaying the contents of the Session object.

              Something like:
              Code:
              DataTable tempdt;
              string n = "";
              if (Session["temptable"] == null)
              {
              	n = "(Empty)";
              }
              else
              {
              	tempdt = (DataTable)Session["temptable"];
              	foreach (DataRow d in tempdt.Rows)
              	{
              		n+="'"+d["Page"].ToString()+"' : "+d["Hits"].ToString()+"</br>\r\n";
              	}
              }
              myLabel.Text = n;

              Comment

              • mikeyeli
                New Member
                • Oct 2007
                • 63

                #8
                Session in .net suck, you have to be extremely careful, and yes they are kinda buggy in my opinion.
                • You should check iis settings, maybe theres a problem there.
                • Check Session timeout.
                • Try something else


                By trying something else, you should consider the fact that saving a whole shopping cart in session can also be e memory problem for the server if there are a lot of users this can be a problem. and your current issue. i think you should consider using a temporary table in the database, containing maybe a list of userid and the product id.

                anyways its just a suggestion, since u seem to be out of time, this can be a fast solution.

                Comment

                Working...