Passing Session Variables to a Web User Control using C#

I have a C# web app with a textbox and some buttons on the main form.
There is also some Web User Controls on the form.
I'm trying to take the text that is in the texbox, put it in session scope, pass it to one of the Web User Controls, and display it in the user control.
It seems like a trival task but I can't seem to get the session variable to display on the web user control.
Could someone tell me how to pass a session variable from a main form to the web user control?
Any advice would be grately appreciated.


Here is the C# code:

index.aspx
======================================
<%@ Register TagPrefix="uc1" TagName="ucNeighborhood" Src="ucNeighborhood.ascx" %>
<%@ Register TagPrefix="uc2" TagName="ucLTAV" Src="ucLTAV.ascx" %>
<%@ Register TagPrefix="uc3" TagName="ucRatioStudy" Src="ucRatioStudy.ascx" %>
<%@ Register TagPrefix="uc4" TagName="ucFindProperty" Src="ucFindProperty.ascx" %>
<%@ Page language="c#" Codebehind="index.aspx.cs" AutoEventWireup="true" Inherits="MLS.frmMLS" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
      <HEAD>
            <title>WebForm1</title>
            <meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
            <meta content="C#" name="CODE_LANGUAGE">
            <meta content="JavaScript" name="vs_defaultClientScript">
            <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
      </HEAD>
      <body>
            <form id="frmMLS" method="post" runat="server">
                  <table id="tblMain" style="MARGIN-LEFT: 8px" cellSpacing="0" cellPadding="0" width="100%" border="1">
                        <tr>
                              <td width="300">&nbsp;</td>
                              <td width="150">&nbsp;</td>
                              <td width="150">&nbsp;</td>
                              <td width="150">&nbsp;</td>
                              <td>&nbsp;</td>
                        </tr>
                        <tr>
                              <td align="center" colSpan="5">&nbsp;<asp:label id="lblTitle" runat="server" Width="112px" Font-Bold="True">MLS Reports</asp:label></td>
                        </tr>
                        <tr>
                              <td>&nbsp;</td>
                              <td>&nbsp;</td>
                              <td>&nbsp;</td>
                              <td>&nbsp;</td>
                              <td>&nbsp;</td>
                        </tr>
                        <tr>
                              <td>&nbsp;<asp:label id="lblSubID" runat="server" Width="128px">Subject Property ID</asp:label></td>
                              <td>&nbsp;</td>
                              <td>&nbsp;</td>
                              <td>&nbsp;</td>
                              <td>&nbsp;</td>
                        </tr>
                        <tr>
                              <td>&nbsp;<asp:textbox id="txtSubjectPropertyID" runat="server" Width="272px"></asp:textbox></td>
                              <td>&nbsp;<asp:button id="cmdNeighborhood" runat="server" Text="Neighborhood"></asp:button></td>
                              <td>&nbsp;<asp:button id="cmdAV" runat="server" Text="Sales LT AV"></asp:button></td>
                              <td>&nbsp;<asp:button id="cmdRatio" runat="server" Text="Ratio Study"></asp:button></td>
                              <td>&nbsp;</td>
                        </tr>
                        <tr>
                              <td>&nbsp;<asp:button id="cmdFindProperty" runat="server" Text="Find Subject Property ID"></asp:button></td>
                              <td>&nbsp;</td>
                              <td>&nbsp;</td>
                              <td>&nbsp;</td>
                              <td>&nbsp;</td>
                        </tr>
                        <tr>
                              <td>&nbsp;</td>
                              <td>&nbsp;</td>
                              <td>&nbsp;</td>
                              <td>&nbsp;</td>
                              <td>&nbsp;</td>
                        </tr>
                        <tr>
                              <td colSpan="5">
                                    <uc1:ucNeighborhood id="UcNeighborhood" runat="server" Visible="False"></uc1:ucNeighborhood>
                                    <uc2:ucLTAV id="UcLTAV" runat="server" Visible="False"></uc2:ucLTAV>
                                    <uc3:ucRatioStudy id="UcRatioStudy" runat="server" Visible="False"></uc3:ucRatioStudy>
                                    <uc4:ucFindProperty id="UcFindProperty" runat="server" Visible="False"></uc4:ucFindProperty>
                              </td>
                        </tr>
                  </table>
            </form>
      </body>
</HTML>




index.aspx.cs
====================================================
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace MLS
{
      /// <summary>
      /// Summary description for WebForm1.
      /// </summary>
      public class frmMLS : System.Web.UI.Page
      {
            public System.Web.UI.WebControls.TextBox txtSubjectPropertyID;
            protected System.Web.UI.WebControls.Label lblTitle;
            protected System.Web.UI.WebControls.Label lblSubID;
            protected System.Web.UI.WebControls.Button cmdNeighborhood;
            protected System.Web.UI.WebControls.Button cmdAV;
            protected System.Web.UI.WebControls.Button cmdRatio;
            protected System.Web.UI.WebControls.Button cmdFindProperty;

            protected ucNeighborhood UcNeighborhood;
            protected ucLTAV UcLTAV;
            protected ucRatioStudy UcRatioStudy;
            protected ucFindProperty UcFindProperty;
      
            private void Page_Load(object sender, System.EventArgs e)
            {
                  // Put user code to initialize the page here
                  Session["subjectPropertyID"] = "";
            }

            #region Web Form Designer generated code
            override protected void OnInit(EventArgs e)
            {
                  //
                  // CODEGEN: This call is required by the ASP.NET Web Form Designer.
                  //
                  InitializeComponent();
                  base.OnInit(e);
            }
            
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {    
                  this.cmdNeighborhood.Click += new System.EventHandler(this.NeighborhoodEngage);
                  this.cmdAV.Click += new System.EventHandler(this.LTAVEngage);
                  this.cmdRatio.Click += new System.EventHandler(this.RatioEngage);
                  this.cmdFindProperty.Click += new System.EventHandler(this.FindPropertyEngage);
                  this.Load += new System.EventHandler(this.Page_Load);

            }
            #endregion

            private void NeighborhoodEngage(object sender, System.EventArgs e)
            {
                  // set visibility
                  UcNeighborhood.Visible = true;
                  UcLTAV.Visible = false;
                  UcRatioStudy.Visible = false;
                  UcFindProperty.Visible = false;
                  // *** the 2 lines below work fine on this page (index.aspx.cs) ***
                  //Session["subjectPropertyID"] = txtSubjectPropertyID.Text.ToString();
                  //Response.Write(txtSubjectPropertyID.Text.ToString());
                  
            }

            private void LTAVEngage(object sender, System.EventArgs e)
            {
                  // set visibility
                  UcNeighborhood.Visible = false;
                  UcLTAV.Visible = true;
                  UcRatioStudy.Visible = false;
                  UcFindProperty.Visible = false;
                  Response.Write(txtSubjectPropertyID.Text.ToString());
            }

            private void RatioEngage(object sender, System.EventArgs e)
            {
                  // set visibility
                  UcNeighborhood.Visible = false;
                  UcLTAV.Visible = false;
                  UcRatioStudy.Visible = true;
                  UcFindProperty.Visible = false;
                  Response.Write(txtSubjectPropertyID.Text.ToString());
            }

            private void FindPropertyEngage(object sender, System.EventArgs e)
            {
                  // set visibility
                  UcNeighborhood.Visible = false;
                  UcLTAV.Visible = false;
                  UcRatioStudy.Visible = false;
                  UcFindProperty.Visible = true;
                  Response.Write(txtSubjectPropertyID.Text.ToString());
            }




      }
}




ucNeighborhood.ascx
==========================================================
<%@ Control Language="c#" AutoEventWireup="false" Codebehind="ucNeighborhood.ascx.cs" Inherits="MLS.ucNeighborhood" TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%>
This is the Neighborhood user control.<br>
<asp:Label id="lblPropertyID" runat="server"></asp:Label>


ucNeighborhood.ascx.cs
===========================================================
namespace MLS
{
      using System;
      using System.Data;
      using System.Drawing;
      using System.Web;
      using System.Web.UI.WebControls;
      using System.Web.UI.HtmlControls;
      using System.Web.SessionState;
      

      /// <summary>
      ///            Summary description for ucNeighborhood.
      /// </summary>
      public class ucNeighborhood : System.Web.UI.UserControl
      {
            protected System.Web.UI.WebControls.Label lblPropertyID;

            private void Page_Load(object sender, System.EventArgs e)
            {
                  // Put user code to initialize the page here
                  lblPropertyID.Text = Session["subjectPropertyID"].ToString();
                  Response.Write(Session["subjectPropertyID"].ToString());
            }

            #region Web Form Designer generated code
            override protected void OnInit(EventArgs e)
            {
                  //
                  // CODEGEN: This call is required by the ASP.NET Web Form Designer.
                  //
                  InitializeComponent();
                  base.OnInit(e);
            }
            
            /// <summary>
            ///            Required method for Designer support - do not modify
            ///            the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                  this.Load += new System.EventHandler(this.Page_Load);

            }
            #endregion
      }
}


FastEddie___Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

dunglaCommented:
You should have a public property in your user control to receive the value of Session from main page:
ucNeighborhood.ascx.cs
=================
private string msubjectPropertyID;
///<summary>
/// write-only property
///</summary
public string subjectPropertyID
{
set ( msubjectPropertyID = value;}
}
 private void Page_Load(object sender, System.EventArgs e)
          {
               // Put user code to initialize the page here
               lblPropertyID.Text = msubjectPropertyID;
               Response.Write(msubjectPropertyID);
          }

========== index.aspx.cs =============
private void NeighborhoodEngage(object sender, System.EventArgs e)
          {
               // set visibility
               UcNeighborhood.Visible = true;
               UcLTAV.Visible = false;
               UcRatioStudy.Visible = false;
               UcFindProperty.Visible = false;
               // *** the 2 lines below work fine on this page (index.aspx.cs) ***
               //Session["subjectPropertyID"] = txtSubjectPropertyID.Text.ToString();
               // sets value of subjectPropertyID
               UcNeighborhood.subjectPropertyID = txtSubjectPropertyID.Text;
          }
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
FastEddie___Author Commented:
Hi dungla,

I folowed your instructions but it did not work. I got no errors but also no display of the string typed into the textbox.
However when I clicked on the other buttons I did see the textbox string at the top of the page from the response write method.
So the response write did work but did not initially show up when I clicked on the "Neighborhood" button.
And the assignment of the subjectPropertyID to the lable :
    lblPropertyID.Text = msubjectPropertyID;
did not work at all.

This seems a little funny to me. If the session variable has already been set then why can't the web user control just use it directly?

The user control is being displayed but without the session variable. For example on the ucNeighborhood.ascx there is text that says:
     "This is the Neighborhood user control.<br>"
That text is showing up including the break character when I click on the neighborhood button but for some reason I'm not able to
display the session variable that is on the next line. This is very wiered to me.

Have you got any other suggestions?

I do appreciate your input.

-Eddie



0
FastEddie___Author Commented:
Oh one more thing to note. This code works fine:

   lblPropertyID.Text="ggggggggg"

This code does not:

    lblPropertyID.Text=Session["subjectPropertyID"].ToString();

So the web user control is there and it is made visible and invisible correctly
however when I try to use a session variable within the code it chokes.



0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

AGBrownCommented:
Try doing this in dungla's code, it should then update the label text each time that you reset the property:
      
    public string subjectPropertyID
    {
        set ( lblPropertyID.Text=msubjectPropertyID = value;}
    }

Of course, if you don't need to store the label text, you could just do

    public string subjectPropertyID
    {
        set ( lblPropertyID.Text = value;}
    }

Does the code "choke" with an exception when you do "lblPropertyID.Text=Session["subjectPropertyID"].ToString();". Could you try and do this instead:
    lblPropertyID.Text=HttpContext.Current.Session["subjectPropertyID"].ToString();

Related to that last comment, I'll go into Session in a bit more detail. Bear with me if you know this already. I'm not sure I agree with the bit about "passing session through a property". It isn't necessary once you understand what Session is and how it works: Session is a "state bag" exposed by the ASP.NET runtime to _all_ code that is running inside the runtime.

If you store something in the Session, any control/class/page/anything can get to it by using the line
    HttpContext.Current.Session["key"] = "value"; (and the opposite to read instead of write)

The System.Web.UI.Page class, which all pages are based on exposes a property called Session which is simply a quick way of getting to HttpContext.Current.Session. It is nothing other than:
    protected HttpSessionState Session
    {
        get { return HttpContext.Current.Session; }
    }
In fact, you can put this exact property into your own classes and controls to make it "easier" to get to the session state.

The point of Session, ApplicationState and Cache are that they are state-persistence stores that are accessible from _all_ objects in the ASP.NET runtime. If you look at the inner workings, then you will see that behind the scenes they are all in fact very inter-related. The differences are that:
1) ApplicationState is available to all user sessions in the application domain on one server.
2) SessionState is (effectively, without explaining how) specific to each user.
3) Cache is like ApplicationState, but has timed expiry for objects (Session is in fact stored using Cache - that's why it expires, unless you lengthen its lifetime in the config files, 20 minutes after it's last access).

To re-emphasise, none of these are specific to any particular page or control. They are accessible from any of your code running in ASP.NET.

This means that you don't have to "pass" them around. To get access to the session state from a page you can use Session. But really you are using HttpContext.Current.Session. So inside a control, or any other class, using HttpContext.Current.Session will give you access to the same "state bag" as using "Session" on a page.

So this brings us to the issue of what you need to achieve. If you are storing values that are specific to a user and that you need to store between postbacks from the client, you use Session. To pass values to and from a control you shouldn't be using Session at all as you are taking up unnecessary server memory and opening yourself up to coupling between classes. Instead you should use a public property to pass the values (as dungla says). You can use a combination of the two to both store and pass values; as dungla showed, you can use the property to pass the value to the control. Using properties to pass values ensures your code always works. Imagine a page that does this:

Session["myKey"] = "aValue";

and a control that does this:

lblMyLabel.Text = Session["myKey"].ToString();

What happens when a well-meaning developer mis-spells the control's line as "Mykey" , or changes "myKey" to something more meaningful and misses the bit in the control which gets the value of myKey from the session. There is no compile-time error to prevent the code from being released, so it can easily get to production.

Instead you should do:
    Session["myKey"] = "value I Want To Store For The Next Postback"; // single point of storage for the session key in all your code
    myControl.MyProperty = Session["myKey"]; // single point of read for the session key in all your code

...with the MyProperty property doing something like we have covered already:

    public string subjectPropertyID
    {
        set ( lblPropertyID.Text=msubjectPropertyID = value;}
    }

If you need to get the value of Session["myKey"] from more than one page, consider implementing a property class with static properties for each session key.
public class SessionProperties
{
    public static string myKey
    {
        get
        {
            return Session["myKey"];
        }
        set
        {
            Session["myKey"] = value;
        }
    }
}

Or, if that is too cumbersome, at least have a central class that defines the keys as constants:
public class SessionKeys
{
    const string SESSION_MY_KEY = "myKey";
}
... page code:
Session[SessionKeys.SESSION_MY_KEY] = "value";

Things like that will help prevent hard-to-find problems in your code later on.

So, after all that, did the suggestions at the top of the post help at all? ;-)

Andy
0
FastEddie___Author Commented:
It helped in that I have a better understanding of how the app should be coded in situations where session and user control properties are mixed. However as you stated, the session scope can be accessed from any location and should not need any special consideration for user controls.

I figured out the problem. I was setting the session to nothing "" on the PageLoad event when it should have been set to nothing in the     if (!IsPostBack)     section only. After I made the change I was able to access the session variable with :

      lblPropertyID.Text=Session["subjectPropertyID"].ToString();

No need for the "HttpContext.Current" prefix but that is good to keep in mind for future reference.

I realize that session is problably not the most effecient way of doing this but it is used only for one variable and it just makes persistence so easy. The app is basically taking a variable and performing differnent types of operations on it. One type of operations per user control. I'm sure that with more expierence I'll be able to find better ways to modularize my code but for now user controls seem to work just fine. I do hate using session when the user control is on the same page though. Oh well...

I'd like to split these points with you and dungla. Now I've got to figure out how to do that.   :-)

Thanks a bunch for your help.




0
AGBrownCommented:
In addition to your statement about persistence, and my rhetoric ;) about state persistence. You may want to go with ViewState to store this calculation variable. Try opening your app, and going to the place where that variable is first created. Then spawn a new Internet Explorer window from the window you are using through File, New Window. Now use the first window to go half way through the variable modification workflow. Now go back to the other window, it will access the same session, so may mess things up for you if it tries to modify the same variable.

ViewState is the state bag to use if you need to store the state of a particular workflow represented by page instances. SessionState helps you store central information that is used by all pages for a user session, and that can be modified by any page in any order without bad effects.

A
0
dunglaCommented:
Thanks AGBrown for correct the answer :)

-D
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.