I am trying to implement a static SessionManager class that is supposed to act as a wrapper around a SessionStore object, which is stored in HttpContext.Current.Session["objSession"] and actually holds all of the user's session data. The SessionManager class has identical properties as SessionStore, but has extra methods needed to manipulate the session data as needed. Basically, the SessionManager facilitates getting/setting properties stored in the session object.
All classes are stored in the same namespace as the web solution, and all are serializable.
I have tried two different solutions to my problem, both threw a null reference exception at the same point, when trying to do ANYTHING with HttpContext.Current.Session:
public static class SessionManager
{
static SessionManager()
{
if (HttpContext.Current.Session != null)
{
try
{
if (HttpContext.Current.Session["objStore"] == null)
{
HttpContext.Current.Session["objStore"] = new SessionStore();
}
}
catch (NullReferenceException)
{
HttpContext.Current.Session["objStore"] = new SessionStore();
}
}
}
Code-behind of the calling page:
protected void Page_Load(object sender, EventArgs e)
{
if (SessionManager.groupSettings.Count > 0)
{
pnlDashboard.Visible = true;
pnlLogin.Visible = false;
getDisplayData();
}
else
{
pnlDashboard.Visible = false;
pnlLogin.Visible = true;
}
}
The debugger steps into SessionManager all the way down to line
if (HttpContext.Current.Session != null)
where it then stops and throws the exception. However, when I hover over the code and the properties dialog opens, it shows that the HttpContext.Current.Session object is NOT null. The resulting call stack is here, but indicates that the source line is if (SessionManager.groupSettings.Count > 0), which is in the code-behind:
[NullReferenceException: Object reference not set to an instance of an object.]
Project.Default.Page_Load(Object sender, EventArgs e) in C:\Users\ASP\Project\Project\Default.aspx.cs:20
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +51
System.Web.UI.Control.OnLoad(EventArgs e) +95
System.Web.UI.Control.LoadRecursive() +59
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2952
My second attempt had all of the code within the static constructor above, but had it in a public static sessionStart() method, which was called above the first if statement in the calling page's code-behind:
protected void Page_Load(object sender, EventArgs e)
{
SessionManager.sessionStart()
if (SessionManager.groupSettings.Count > 0)
{
pnlDashboard.Visible = true;
pnlLogin.Visible = false;
getDisplayData();
}
else
{
pnlDashboard.Visible = false;
pnlLogin.Visible = true;
}
}
I am really stumped as to what could be causing this problem. I have static classes elsewhere in my code and haven't had any issues, and the Session seems to not be null.
I appreciate all help. Thank you!
So it seems I did not initialize some objects within my SessionStore class, because I added a constructor that initialized them, and the problem is now fixed. Maybe the problem was actually happening when the object was being serialized (as is the case when an object is stored into the stateserver), and the error message confused me.
Edit - I always do this... Figure out the solution AFTER I've posted to StackOverflow... :(
Related
I'm new to ASP.NET :) and I'd like to understand more about session. Here's a simple example: Every time I click the button it will add one more integer to listInt and I store the list using Session["listInt"].
public partial class TestSession : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (Session["listInt"] == null)
{
Session["listInt"] = new List<Int16>();
}
}
}
protected void AddInt_Click(object sender, EventArgs e)
{
Int16 i = 0;
List<Int16> listInt = (List<Int16>)Session["listInt"];
listInt.Add(i);
Session["listInt"] = listInt;
Response.Write("Hello!");
}
}
Here's the thing I don't understand, if I comment the line Session["listInt"] = listInt;, whenever I click the variable Session["listInt"] still store the value (means still add more integer to the list):
Int16 i = 0;
List<Int16> listInt = (List<Int16>)Session["listInt"];
listInt.Add(i);
//Session["listInt"] = listInt; //No idea why....
Response.Write("Hello!");
Can anyone please tell me how session works in this case? Thanks in advance :)
Your list is a reference type, so when you retrieve it from the server via the session state container you actually get a reference to some object in the server memory. Hence no need to reassign it later.
I am new to c# and kind of winging it. using Microsoft Visual C# 2010
I have checked many similar posts and none of the suggestions seem to help
I am getting the following error: "Cannot access a disposed object"
which references the main form here
private void btn_RunPkgs_Click(object sender, EventArgs e)
{
RunPackages rp = new RunPackages();
this.Hide();
rp.ShowDialog();//The error points to this line
this.Show();
}
here is the code that blows up when the security check fails.
private void securityCheck()
{
if (MyGlobals.FormCheck("RUN_JOBS") == 1)
{
InitializeComponent();
}
else
{
//this.BeginInvoke(new MethodInvoker(this.Close));
//this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
MessageBox.Show("You do not have permission to access this form!");
//this.Close();
this.Dispose();
}
}
EDIT
It looks like I am going to go with Adriano Repetti's idea of putting the security where I call the page, but I am a little nervous now having any security on the page.
private void btn_RunPkgs_Click(object sender, EventArgs e)
{
if (MyGlobals.FormCheck("RUN_JOBS") == 1)
{
RunPackages rp = new RunPackages();
this.Hide();
rp.ShowDialog();
this.Show();
}
else
{
MessageBox.Show("Not for You!");
}
}
private void btn_ListUpdater_Click(object sender, EventArgs e)
{
if (MyGlobals.FormCheck("MDM") == 1)
{
ListUpdater lu = new ListUpdater();
this.Hide();
lu.ShowDialog();
this.Show();
}
else
{
MessageBox.Show("Private!");
}
}
EDIT2
Came up with the following possible solution but am nervous to use it because I am new at this and don't know what issues there might be. Any problems with just creating an event handler for form load?
namespace RunPackages
{
public partial class ListUpdater : Form
{
public ListUpdater()
{
InitializeComponent();
this.Load += new EventHandler(securityCheck);
}
private void securityCheck(object sender, EventArgs e)
{
if (MyGlobals.FormCheck("MDM1") == 0)
{
MessageBox.Show("Not Allowed!");
this.Close();
}
}
You can't dispose of the form within the form itself. The ShowDialog() method tries to access the form on exit for things such as DialogResult.
After a form has been disposed almost all of its methods can't be accessed (and most of its properties are invalid).
In your first line of btn_RunPkgs_Click() you create an object and you dispose it inside its constructor. Per se, even if pretty bad habit you may even call Dispose() from within constructor, it may even work but then you try to use such object ShowDialog() will generate ObjectDisposedException. Note that this code will also lead to same result (an exception):
RunPackages rp = new RunPackages();
rp.Dispose();
Yes you may check IsDisposed but that won't make code readable and problem (IMO) is you're mixing things. Constructor shouldn't contain such logic.
The point isn't just where you dispose your form. What's better is to don't even create such form (let me assume, because you call InitializeComponent(), that securityCheck() is called inside form constructor), for this you may use a factory static method:
public static bool TryShowDialog(Form currentForm)
{
if (MyGlobals.FormCheck("RUN_JOBS") != 1)
return false;
if (currentForm != null)
currentForm.Hide();
RunPackages dlg = new RunPackages();
dlg.ShowDialog();
if (currentForm != null)
currentForm.Show();
return true;
}
Your calling function will then be reduced to:
private void btn_RunPkgs_Click(object sender, EventArgs e)
{
RunPackages.TryShowDialog(this);
}
Note that such function is highly eligible for some refactoring (for example to extract code to hide/show existing form). Something like this:
public static bool ShowDialog<T>(Form currentForm, string authorizationId)
where T : Form, new()
{
if (MyGlobals.FormCheck(authorizationId) != 1)
return false;
if (currentForm != null)
currentForm.Hide();
T dlg = new T();
T.ShowDialog();
if (currentForm != null)
currentForm.Show();
return true;
}
Used like this (now code is reused everywhere):
SecurityHelpers.ShowDialog<RunPackages>(this, "RUN_JOBS");
Please note that calling code may be simplified (authorizationId may be an attribute on RunPackages, for example, and also currentForm can be deduced from current active form).
EDIT Calling Close() isn't better, if window handle has not been created (let's simplify little bit: it's created when window is shown) internally it'll call Dispose() (then above applies).
I would not try to disrupt the chaining of events that lead to the form creation.
The side effects are difficult to predict and what works today could not work in future versions.
Instead I would try a different approach
private void securityCheck()
{
if (MyGlobals.FormCheck("RUN_JOBS") == 1)
{
InitializeComponent();
}
else
{
Label message = new Label();
message.Dock = DockStile.Fill;
message.Text("You do not have permission to access this form!.");
message.TextAlign = ContentAlignment.MiddleCenter;
this.Controls.Add(message);
}
}
In this way I let the form show with just one label that covers the entire form surface with your message. The user could only close the form (provided that you have not removed the Control Box)
By the way, this has the advantage of avoiding dangerous oversights because it doesn't require any change on the calling code and the final effect is to effectively block the use of the form.
If you insist in closing the form during its constructor phase then you could get some advices from this question
I came up with the following, can anyone tell me if there are any issues with this?
namespace RunPackages
{
public partial class ListUpdater : Form
{
public ListUpdater()
{
InitializeComponent();
this.Load += new EventHandler(securityCheck);
}
private void securityCheck(object sender, EventArgs e)
{
if (MyGlobals.FormCheck("MDM1") == 0)
{
MessageBox.Show("Not allowed!");
this.Close();
}
}
etc...
Use a flag. For example change the code, like this:
public bool IsDisposed;
private void securityCheck()
{
if (MyGlobals.FormCheck("RUN_JOBS") == 1)
{
InitializeComponent();
}
else
{
//this.BeginInvoke(new MethodInvoker(this.Close));
//this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
MessageBox.Show("You do not have permission to access this form!");
//this.Close();
this.Dispose();
this.IsDisposed = true;
}
}
Then:
private void btn_RunPkgs_Click(object sender, EventArgs e)
{
RunPackages rp = new RunPackages();
if(rp.IsDisposed)
return;
this.Hide();
rp.ShowDialog();//The error points to this line
this.Show();
}
I have a custom error handler for an asp.net site.
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
//if (System.Configuration.ConfigurationManager.AppSettings["ProductionMode"] == "Yes")
#if (!DEBUG)
Server.Transfer("~\\GlobalExceptionHandler.aspx");
#endif
}
It works fine and dandy when retrieving exception information cause it'll just snag Server.getLastException() and email it on to me for review
However, I have some TextBoxes on the page and I'd like to send the value of those textboxes along with the email. Maybe it's not quite the DOM I'm looking for access to but instead those posted variables.
I tried looking at HttpContext.Current.Request.Form but it showed no keys.
So Does anyone know how to access the formvalues when globally catching an exception?
Accessing the Form Values
To access the form values in Global.Application_Error, you can simply use HttpContext.Current.Request.Form.
Here is a proof of concept, where a page immediately throws an exception on post(back) to hit the application error handler:
void Application_Error(object sender, EventArgs e)
{
var test = HttpContext.Current.Request.Form;
}
Setting a breakpoint on the assignment to test, then stepping over it (with F10) when it is hit, you can see that test is indeed set to the post(back)'s form-values collection.
Accessing the Postback Control Values
Alternatively, you can access the postback control values by adding them to the session on postback, for example...
// ************code behind
protected void TextBox1_TextChanged(object sender, EventArgs e)
{
Session["TextBox1"] = TextBox1.Text;
}
..., and accessing the session in the application error handler - for instance:
// ************Global.asax.cs
protected void Application_Error(object sender, EventArgs e)
{
// Use Session["TextBox1"].
}
A CodeVerge thread speaks to approach well - particularly Benson Yu's reply.
I want to validate winform using error provider. When user click on button multiple Validated methods are executed txtFieldOne_Validated(this, e); txtFieldTwo_Validated(this, e); and I need solution to stop execution further if any of this validators fails and display error using error provider.
I thought to use private variable bool _formValid like
private btnValidateFields_Click(object sender, EventArgs e)
{
txtFieldOne_Validated(this, e);
txtFieldTwo_Validated(this, e);
if(_formValid)
{continue...}
}
private void txtFieldOne_Validated(object sender, EventArgs e)
{
if(....)
errorProvider1.SetError(txtFieldOne, "some error message")
_formValid = true;
else(....)
errorProvider1.SetError(txtFieldOne, "")
formValid = false;
}
but using this approach if last checked field was true than populated _formValid remains true and form pass.
I am not clear what you are trying to do. But as per your comments, I will suggest something like this.There is no need to call different Validation method for different controls. All controls should be validated in same method.
void IsFormValid(this, e)
{
bool result = ValidateAllControls();
if(!result)
return;
// Rest of the execution
}
bool ValidateAllControls()
{
if(!control1.IsValid)
return false;
if(!control2.IsValid)
return false;
if(!control3.IsValid)
return false;
return true;
}
Let me know if I misunderstood something.
Hope it helps.
now i have the current code o MainUC.cs:
private void tsbNoviRacun_Click(object sender, EventArgs e)
{
if (racunuc == null)
{
racunuc = new RacunUC();
racunuc.Dock = DockStyle.Fill;
Controls.Add(racunuc);
}
racunuc.BringToFront();
The thing i want to do is clean the code from main page/form. I have 2 taskbar and 2 toolbar buttons that are calling the same form (this one above), so i don't want to write the code 4 times. I tried to make new class.cs with properties and do it with return value, but it didn't work. Can someone help me with it, or, is there possiblity to call the same code on current page/form. Something like
private void tsbStariRacuni_Click(object sender, EventArgs e)
{
call tsbNoviRacun();
}
"( this isn't working, i know :p)
EDiT: Oh damn me, thanks guys!
In c# there is no "call" keyword for invoking functions. You just type the name and all required arguments in round brackets.
private void tsbStariRacuni_Click(object sender, EventArgs e)
{
tsbNoviRacun_Click(sender, e);
}
This should do it:
public void tsbNoviRacun()
{
if (racunuc == null)
{
racunuc = new RacunUC();
racunuc.Dock = DockStyle.Fill;
Controls.Add(racunuc);
}
racunuc.BringToFront();
}
private void tsbNoviRacun_Click(object sender, EventArgs e)
{
tsbNoviRacun();
}
You can call that method from all the event handlers you want it to run on. Obviously this function is depended on Controls and DockStyle so you must put it within scope of this.