ASP.NET variable scope - asp.net

im really new to ASP.Net and still havnt got my head round most of the concepts, im really having problems with variable, when creating a desktop application, any variable created in code for example
int n = 10;
this variable will be there until the program is running right. but in asp iv created variables which are supposed to last until the user gets of that page, so for example say i have a page which takes the users value ( call this variable n say the user type in 10) and every time the user presses the next button the code add 10 to this value. so the first time the user presses the next button
n= n + 10;
what i have found is no matter how many times i press the next button n will always equal 20, because the previous value is not saved !!
these values are populated the first time the user enters that page, once the user clicks the next button the content of these values disappear! how can stop this from happening ??
hope this makes sense !!
thanks

Every time you refresh page (click also refreshes page) new instance of Page class is created. This means that all your fields become empty.
You can try to use ViewState to persist data between refreshes. But you should be care as this will increase page size. So best practice is to minimaze data in view state.
Another options is SessionState, but in this case you will keep data even between pages.
Hope this helps.

Each time the user requests the page, it receives the request, is initialized, processed, and then rendered (read about the Asp.Net Page Life Cycle here.). So, on each page request, your variables are being created, initialized, and then assigned your values - each page load is a new life cycle. If you want values to persist betwen page life cycles, then you need to use one of the available methods (ViewState, Session, QueryString, Post, ....) to pass the values to the "next" request.

Variables don't automatically maintain state across page calls in ASP.NET. Asp.Net Page has a life cycle and being stateless, the information is lost at the end of this cycle, after a request has been served on the client side. There are several solution for this.
session
hidden fields
querystrings
Here is hidden field example.
In HTML, you simply create:
<input type="hidden" id="myHiddenVar">
To set it's value in javascript:
document.getElementById("myHiddenVar").value = "myValue"
In ASP.NET code-behind, you use the Request object to retrieve the value.
string myHiddenVar = (string)Request.Params["myHiddenVar"];

Variables in ASP.NET work exactly the way that variables in Windows Forms work:
public class MyPage : System.Web.UI.Page
{
private int n = 0;
public void Button_Click(object sender, EventArgs e)
{
n = n + 1;
}
}
public class MyForm : System.Windows.Forms.Form
{
private int n = 0;
public void Button_Click(object sender, EventArgs e)
{
n = n + 1;
}
}
So, why is it with the page, that the old value of "n" is gone the next time you hit the page?
Because HTTP is a request/response protocol. Each request creates a new instance of your MyPage class, each with its own copy of "n". In a Windows Forms application, you're probably not creating a new instance of your form on every button click!

Related

Asp.net Wizard Control with Dynamic Steps gets stuck

I have a wizard control which must use dynamic steps in. I have the following code which loads the dynamic steps (this all works fine). I have 7 static steps.
protected override LoadViewState(object savedState)
{
base.LoadViewState(savedState);
int offset = 4;
foreach(string stepName in this.ViewState["Steps"])
{
WizardStep step = new WizardStep();
step.Title = stepName;
this.Wizard1.WizardSteps.AddAt(step, offset); // LINE 1
this.Wizard1.WizardSteps.Add(step); // LINE 2
offset++;
}
}
I have two issues, when I execute the code and use Line 1. When I get to a dynamic step it won't let you procede to the next one (using the Next button). This seems to be because this.IsValid is false (but I have no validation controls on the page). It just seems to get stuck on that current page.
When I run using Line 2, it adds the steps again fine. When I am on the first dynamic step and click Next I get the error. ActiveViewIndex is being set '7'. It must be smaller than the current view controls '7'. For dynamically added views, make sire they are added before or in Page_PreInit event.
The issue with the second error is I can't add the dynamic steps in Page_PreInit because I need access to the viewstate to know how many steps to draw.
I found the issue. Its since the steps must be added in the Page_PreInit event. Which does mean I can't use the Viewstate but I am using the Session instead now.

How to prevent multiple browser windows from sharing the same session in asp.net

I have ASP.net application that is basically a data entry screen for a physical inspection process. The users want to be able to have multiple browser windows open and enter data from multiple inspections concurrently. At first I was using cookie based sessions, and obviously this blew up.
I switched to using cookie-less sessions, which stores the session in the URL and in testing this seemed to resolve the problem. Each browser window/tab had a different session ID, and data entered in one did not clobber data entered in the other.
However my users are more efficient at breaking things than I expected and it seems that they're still managing to get the same session between browsers sometimes. I think that they're copying/pasting the address from one tab to the other in order to open the application, but I haven't been able to verify this yet (they're at another location so I can't easily ask them).
Other than telling them don't copy and paste, or convince them to only enter one at a time, how can I prevent this situation from occurring?
Think of using ViewState instead of Session, since ViewState renders state information to the client (HTML page). I'm not sure if you'll ever be able to gain detailed control over the browser's session behaviour, because the session ID is maintained by the browser the way the manufacturer did it. So ViewState is more predicable, not only but also for future browser versions.
this is a very good question that i have also thought long and hard about.
Store your main web page in an iframe. Have javascript to check if your web page is still in the parent iframe. If not, then they have opened multiple browser windows.
You need to make sure your entire app is iframe friendly.
I am unsure why you wish to restrict a session to handle only one inspection process, and then force multiple sessions in order for users to work simultaneously on multiple inspections. That feels like a rather awkward style of isolation.
The web application (and pages) ought to be able to handle multiple inspection processes within a single user session.
Whatever data that is being held in Session variables should not be plainly exposed for singular handling. They ought to be stored in collections that readily identify which set of data belongs to which inspection process. Every page submission back to the web server ought to carry an identifier which inspection process it pertains to, so that the correct session set can be matched and pulled for use.
pseudo code concept
var inspectionID = this.inspectionLabel.Text;
var inspectionSets = (Hashtable)Session["inspections"];
var inspection = (Inspection)inspectionSets[inspectionID];
Must the users be logged in with different accounts to access different physical inspections? It seems to me that as long as the PhysicalInspectionID is part of the URL, then there should be no problem in editing multiple physical inspections at the same time.
E.g.,
http://inspections.mydomain.com/edit/23
Of course, if they copy the URL, they will get a duplicate of the other window, but this will teach them not to do that. Instead, they open another window and browse to the proper inspection (or add a new one) via the UI.
This is what I use in ASP.NET MVC to forbid authenticated users to open multiple tabs:
<script language="javascript" type="text/javascript">
#if(Request.IsAuthenticated)
{
<text>
if (window.name != 'singleWindow') {
window.location.href = "Content/ErrorPages/SingleTab.htm";
}
</text>
}
else
{
<text>
window.name = "singleWindow";
</text>
}
</script>
Basically, this sets the window name first time when the user visits the login page. After logging in, for each subsequent page load the window name is tested.
Two problems:
does not wok if JavaScript disabled
if by mistake the user closes the original tab and then pastes some other link to my website in the address bar, the user will always receive the error page. To give the user a chance to recover, I have included "Log out" link in the SingleTab.htm page, so the user can destroy his session cookie and start a new session.
A solution to that problem can be implemented by the following:
public static class CommonHelper
{
public static bool SiteGuard
{
get
{
if(HttpContext.Current.Session["SiteGuard"] == null)
return true;
return (bool)HttpContext.Current.Session["SiteGuard"];
}
set
{
HttpContext.Current.Session["SiteGuard"] = value;
}
}
}
public partial class TestPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
bool go = false;
for(int i = 0; i < 50; i++) // wait for the service to work (5 secs max)
{
if(CommonHelper.SiteGuard)
{
go = true;
break;
}
Thread.Sleep(100);
}
if(!go)
Response.Redirect("Login.aspx");
SiteGuard = false; // from now on, nobody can visit your site
}
// Now as long as Page.IsPostBack is true you are in a good shape
}
}
Add an asmx web service (or any other type of services you think is suitable) to your root project and add the following method to it:
[WebMethod(EnableSession = true)]
public void FreeSiteGuard()
{
HttpContext.Current.Session["SiteGuard"] = null;
}
In the master page, or on every page add the following javascript:
<script type="text/javascript">
window.onbeforeunload = function (e) {
e = e || window.event;
if (e) {
// Invoke web service
YourProject.YourWebServiceName.FreeSiteGuard();
}
};
</script>
Note that your site response time gets affected by the speed of the web service.
Create a new sessionId when the request has no referer.
That solves the copy-paste url problem.
Store the sessionId in the url like you did.

delete row's in RepeaterControl in ASP.net

I write this code for delete from repeater,but I have a problem.
when I run my page ad delete one of rows , this row is deleted and when I refresh that page , another one rows deleted that I don't want delete that.in fact I want to delete one row but delete two row when I refresh page
protected void SendBoxrep_ItemCommand(object source, RepeaterCommandEventArgs e)
{
MembershipUser Admin = Membership.GetUser(User.Identity.Name);
if (e.CommandName == "del")
{
Guid g = new Guid(e.CommandArgument.ToString());
MessageClass.deleteMessage(g);
SendBoxrep.DataSource = MessageClass.selectMessagesUser(Admin);
SendBoxrep.DataBind();
}
}
public static void deleteMessage(Guid id)
{
foreach (Message item in MessageClass.LoadAll(id))
{
MDB.Messages.DeleteOnSubmit(item);
MDB.SubmitChanges();
}
}
In a scenario like this, I've had success using Response.Redirect to reload the page and get rid of the postback information after the postback event has been handled. This way the postback will happen only once and refreshing the page using the browser shouldn't cause any problems. Instead of calling the Repeater.DataBind...
Response.Redirect(Request.RawUrl);
You may have to make design changes to other parts of your page or add a parameter to the query string indicating that you are reloading the page, but that's the tax of providing this ability.
Try to delete based on primary key of the table u r deleting.
Suppose u r deleting a table say Messages which has messageID as primary key.
Now if u want to delete a particular message then send the messageID as commandArgument and delete that.
After delete when you r refreshing the page the same event occurs i.e. if you press a delete button in a row to delete the message the event SendBoxrep_ItemCommand fired and taking the commandArgument it deletes the record. Again you press F5 to refresh the page then the previous event for delete is fired. So your two records are being deleted.
Now using primary key (messageID) it will delete only one record even if you fire the same event twice by pressing F5.
Comments above show you're refreshing your page via F5; this is known to cause problems on ASP.NET pages because of how they post back, an how their lifecycle works. I recommend instead creating a Refresh button on the page itself, that does the postback and updates the necessary information the Repeater is bound to.

ASP.NET page contains dynamic elements, loading takes time

I am dynamically creating a table of checkboxes on my test.aspx page. The dimensions (row and column count) of the table are determined by querying the database.
In test.aspx page, I do the following:
<script language="C#" runat="server">
protected void Page_Load ( object src, EventArgs e ) {
//Query the database to get the data for rows and columns
CheckBox[] chkBox = new CheckBox[rows * columns]; //creates a collection of checkboxes
//Iterate over the query set in a double for loop to create dynamic checkboxes
}
</script>
Right now I have the number of rows=20 and columns=10, but it can increase (with the columns more likely).
I used the Net tab in Firebug to ascertain the time taken by different events and found that GetTest.aspx is taking close to 4 minutes, which is too long a time to wait.
Is there a way to being down the page load time? Is my approach to create dynamic check boxes correct?
Thanks in advance.
cheers
I'm looking at this comment:
// Query the database to get the data for rows and columns
You gloss over this, but 9 times out of 10 when a web page loads slowly it's because it's performing some slow database operation.
My guess is that either (a) you have a very inefficient database query, perhaps due to a lack of indexing, or (b) you're running a database query inside a loop somewhere (very bad).
ASP.NET can create thousands of checkboxes in less than 1 second. It's just class instantiation. The issue is somewhere else.
Enabling ASP.NET trace on the page and see where all the time is spent. Four minutes is of course way too long for any page. You list two though... test.aspx and GetTest.aspx... what is GetTest.aspx?
EDIT:
OK, you are not telling us the whole story here. What else is this page doing? Where are these controls going? I just tried this on a test page using code similar to that above and it renders in a split second.
Like I said... enable TRACE and find out what is really taking up all the time! Use the tool, that's why it's there.
Creation of controls (CheckBox) and adding to a holder from the server-side is very inexpensive. Considering you are not creating billions.
The HTML that is generated should not be big enough to take 4 minutes on a local machine.
Please check the generated HTML size to verify its mass.
If I were you then I would have written the following code on my server. Please consider.
protected void Page_Load(object src, EventArgs e) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
holderPanel.Controls.Add(
new CheckBox {
ID = string.Format("chk{0}{1}", i, j),
Text = "some text"
});
}
}
}
Consider the holderPanel is a server side asp:Panel or a simple Div with ID = "holderPanel" and runat="server"
Try disabling Firebug & see if it still takes that long. Also double check that your code didn't generate more checkboxes than you expected.

How does one discard a session variable while closing Web Page?

We are following a procedure in our work while developing a web page, is to bind page to one or more session variables, these session variables are used only for that page, to hold current processing objects, so while closing page no need for them.
How could I discard these session variables while closing page?
Any suggestions regarding that technique or how to solve that problem?
There is no server-side event that is raised when a page is left/closed. Also the Session_End event (mentioned in other answers) is not called when a page is left, since the user might navigate to other pages of the same web application (and therefore the session will continue to exist).
I can think of 3 possible ways to solve (or work around) this issue:
1 - use ViewState to store data with page-scope. This is what ViewState is made for, and unless you have a lot of data, it should not be a problem. If you have a lot of data, remember, that it will be serialized/deserialized and sent to the client/back to the server for every request (which may result in large requests and therefore bad performance).
2 - instead of putting the data into the session, put it into the Cache (with a low sliding expiration timeout). On your page, you can access your data in the same way as from the session, i.e. data = Cache["data"], but you have to be prepared that the data was removed from the Cache (you have to re-load it again from DB for example), if the time between two requests was bigger than the expiration time.
3 - use the client-side (javascript) onUnload event, and trigger some action (e.g. a ajax callback) to remove the data from the session. But I think the onUnload event is not reliable (it will not be fired in any case, e.g. when the browser is terminated by a crash or with the task manager, or if javascript is disabled).
If you use variables for only that page, store them in viewstate. ViewState is suitable for page scoped variables.
If you are using ASP.NET sessions (which you probably are), you can add a global.asax file to your soluting. In there this event-delegate is to be found (if not, create it):
protected void Session_End(object sender, EventArgs e)
{
}
.. In here you can clear your session collection.
protected void Session_End(object sender, EventArgs e)
{
Session.Clear();
}
This will be fired when the session expires or when a user clicks logout :)

Resources