ASPNET 1.1 Session State Update - asp.net

I'm planning to start using Out-Of-Proc Session State (to use NCACHE) for a web app that is very session-intensive (many things can be downgraded to viewstate). The initial review we need to do is kind of easy (just verify what objects are inserted) but the hard part is to verify what will happen if someone gets an object from session and then updates the object.
Question: Will that object update the session bag automatically? or will I have to update again the session bag with the new updated version? Does it make a difference if using State Server vs Sql Server?
Just some basic example:
private void Page_Load(object sender, System.EventArgs e)
{
MyClass c = (MyClass)Session["c"];
if (c != null)
Response.Write(c.Comments);
if (!Page.IsPostBack)
{
c = new MyClass();
c.Comments = "No Postback " + DateTime.Now.ToString("hhmmssff");
Session["c"] = c;
}
else
{
c = (MyClass)Session["c"];
if (c != null)
{
c.Comments = "Postback " + DateTime.Now.ToString("hhmmssff");
}
}
}
My believe is that the above code would not update the session (so on later postbacks I would always see the same value). However, it does!!!. So I'm not sure WHY? I read many urls where people say that the session does not get updated, and they need to do an explicit overwrite.
The test I'm doing is an ASPNET1.1 Web Application, where state server is configured to my LAN IP address (not localhost or 127.0.0.1).
Thanks for the attention,
KAT LIM

Related

Retain the session value when browser is opened for the second time

First time login to the asp.net application,stored some session value
Eg: Session["Test"]="Saving Sesison";
Logout the application
When opened the browser for the second time,need to retain the same session value.
Eg: Session["Test"]="Saving Sesison";
How can i do that,can anyone help me with some solution to proceed further please.
if (!Page.IsPostBack)
{
if (Session["Test"] == null)
{
Binding data to repeater control(with out filter)
}
else
{
//Get Session value (To maintain session value across the browser)
var cookieSession = Request.Cookies["Test"]; //While opening the browser for the 2nd time,this line is getting null for all the browsers,but session is getting value for firefox & Chrome not for IE { Session["Test"] }
if (cookieSession != null &&!String.IsNullOrEmpty(cookieSession.Value))
{
Session["Test"] = cookieSession.Value;
}
Binding data to repeater control(with filter using session value)
}
}
//On Drop down selection.
protected void Dropdown_SelectedIndexChanged(object sender, EventArgs e)
{
Binding data to repeater control(based on the dropdown selected value)
Session["Test"] = Dropdown.SelectedItem.Text.ToString(); //To maintain the Dropdown selection all over the app
// Set it
if (Session["Test"] == null)
{
Session["Test"] = Guid.NewGuid().ToString();
var cookie = new HttpCookie("Test", (string)Session["Test"]);
Response.Cookies.Add(cookie);
}
}
ASP.NET Session scope is for only particular session only. So its not possible to have that kind of functionality.
But you can use Cache in same way and it will be there until you make it null or time period exceeds. But beware of fact that it will be there for every browser. So either you need to use different key(Unique key) not like 'test'
You have a few options. Though sessions should be sticky between a browser being re-launched assuming it's not in private/incognito mode. If you're finding the session is timing out too quickly you can extend it in Web.config
<system.web>
<sessionState timeout="10080" mode="InProc" />
</system.web>
Where timeout is in minutes. Note: If you're are debugging stopping and starting the debugger will reset your sessions. So will any kind of re-deployment of the application on IIS. If this is an issue for you, you should check out using something like the SQL session state provider: http://msdn.microsoft.com/en-us/library/vstudio/h6bb9cz9(v=vs.100).aspx
Another method of dealing with this is to store some kind of token in a cookie (again, only works if the browser is not in incognito/private mode, and the user data hasn't been flushed).
// Set it
if (Session["Test"] == null)
{
Session["Test"] = Guid.NewGuid().ToString();
var cookie = new HttpCookie("Test", (string)Session["Test"]);
Response.Cookies.Add(cookie);
}
// Get it
var cookieSession = Request.Cookies["Test"];
if (cookieSession != null && !String.IsNullOrEmpty(cookieSession.Value))
{
Session["Test"] = cookieSession.Value;
}
As a note using the SQL session state provider while is one of the more persistent storages there can be some serious overhead requirements. It's easy to rack up a couple of gigs worth of sessions that are being tracked.
In my experience a combination of cookies and the session provider seem to work best if you need to be very certain that some things are sticking to a users experience on the site.
Edit
So the issue with your drop down selection saver is it's always false and should never set the cookie.
protected void Dropdown_SelectedIndexChanged(object sender, EventArgs e)
{
//Binding data to repeater control(based on the dropdown selected value)
// add to Session
Session["Test"] = Dropdown.SelectedItem.Text.ToString();
// Add Cookie
var cookie = new HttpCookie("Test", (string)Session["Test"]);
Response.Cookies.Add(cookie);
}
Now to get your data back out, put this code in the actions/controllers to run BEFORE you try to access Session["Test"]
var cookieSession = Request.Cookies["Test"];
if (cookieSession != null && !String.IsNullOrEmpty(cookieSession.Value))
{
Session["Test"] = cookieSession.Value; // Should contain the selected text from the drop down
}

Delete a record as ending a session

I want to delete a record from data base as a user close the browser. the record which i want to delete is belong to the user who close the browser or log out. I write this code in global but it doesn't work. Can any body help me.
Note: I want to delete the record that has username of log outed user.
thank you very much
the global code:
void Session_End(object sender, EventArgs e)
{
string connStr = ConfigurationManager.ConnectionStrings["dbconn"].ConnectionString;
SqlConnection sqlconn = new SqlConnection(connStr);
SqlCommand sqlcmd = new SqlCommand("delete ChatRoomList where UserName=#UserName", sqlconn);
sqlcmd.Parameters.AddWithValue("#UserName", (string)Session["User"]);
sqlconn.Open();
sqlcmd.ExecuteNonQuery();
sqlconn.Close();
}
There is no reliable way to achieve this. Session_End event would only fire for in-process session state storage and the trigger point would be session expiration which is different than the browser close or user log-out.
So in your case, you may observe the event when your session actually gets timed out (if you have a logout link then you can force session expiry using Session.Abandon)
There are some other ways such as making an AJAX call to server to tell that user has logged out (or closing the browser window) and they may provide you with better results but again not 100% reliable. The most reliable way that I can think of is to have your own timer - i.e. to ping the server (using AJAX call) periodically from browser side and when pings are not received within certain time-out value, assume the user session to be dead/ended.
It will work on IE
window.onbeforeunload = function (event) {
if (((window.event.clientX || event.clientX) < 0) || ((window.event.clientY || event.clientY) < 0)) // close button
{
//call here you you jQuery function to delete either page method, web service or http
}
if ((window.event.clientX < 0) || (window.event.clientY < 0)) // close button
{
//call here you you jQuery function to delete either page method, web service or http
}
else if (window.event.altKey == true || window.event.ctrlKey == true) // ALT + F4
{
//call here you you jQuery function to delete either page method, web service or http handler
}
else // for all other unload events
{
}
}
});

How to Execute Task in BackGround or After Some Condition meets in ASP.NET?

I'm having about 50 Application Variables for Each Search Data Bases. Total 50 Search Db which are querid from Single Search.aspx page depending upon the QueryString passed in URL it connects to Specific DB.
Eg: if Search.aspx?li=1 then Connect to 1SearchDB
if Searcg.aspx?li=2 then Connect to 2SearchDB.....
50SearchDB I am Maintaining the Total Visitors to each SearchDB depending upon the QueryString in URL and increment the Application Variable that are in GLOBAL.ASAX file.
In Global.asax:
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
Application["1"] = 0;
Application["2"] = 0;
.
.
Application["50"] = 0;
}
In Page Load of Search.aspx.cs:
int LocalBody = Convert.ToInt32(Request.QueryString["li"]);
public void Page_Load(object sender, EventArgs e)
{
Label1.Text = GetHits(LocalBody).ToString();
}
private int GetHits(int LocalBody)
{
int counter=0;
switch (LocalBody)
{
case 1:
Application["1"] = (int)Application["1"] + 1;
counter=(int)Application["1"];
break;
case 2:
Application["2"] = (int)Application["2"] + 1;
counter=(int)Application["2"];
break;
.
.
case 50:
Application["50"] = (int)Application["50"] + 1;
counter=(int)Application["50"];
break; default:
break;
}
return counter;
}
Now, i want to Add these Application Variable to QUEUE and on Reaching 1000 or after Some Specified TIME INTERVAL say 20 Minutes it must Write the values to DB or Windows Event Log.
Whether to Write any Service or else...!
The Application object will remain in memory for as long as the WebApp is in memory. IIS can shut down the WebApp if there is no request for some amount of time. In that case the values stored in the Application object would be lost. Assuming even if IIS doesnt shut down the web app, the object resides in the memory of the site. No external service can access this object till you persist it to some shared location (say a database or a message queue).
My suggestion would be not use the application object. Instead persist it to an inmemory store. I am assuming the reason you dont want to persist to the database every time the value updates is so as to avoid writing to disk. Hence am suggesting using a message queue like MSMQ or DotNetMQ or a key value store like Redis.
Once you have your data persisted in a shared location, you can have a service poll the location and save every 1000 items or every 20 mins.

Can't redirect to another page using ASP.NET and WF 4

I am using WF 4 with ASP.NET and as part of the workflow the system may need to redirect to other pages for the user to input additional information under certain circumstances. Once they have entered that information, the system needs to resume the workflow where it left off.
I have this code so far in the initial page that kicks off the process and an activity in the workflow that sets a bookmark.
static InstanceStore instanceStore;
static AutoResetEvent instanceUnloaded = new AutoResetEvent(false);
static Guid id;
protected void Page_Load(object sender, EventArgs e)
{
SetupInstanceStore();
}
protected void btnStartWorkflow_Click(object sender, EventArgs e)
{
app = Session["applicant"];
Dictionary<string, object> workflowInputs = new Dictionary<string, object>();
workflowInputs.Add("Applicant", app.Applicant);
WorkflowApplication workflowApplication = new WorkflowApplication(new IdentityCheckActivites.IdentityCheckWorkflow(), workflowInputs);
workflowApplication.InstanceStore = instanceStore;
//returning IdleAction.Unload instructs the WorkflowApplication to persist application state and remove it from memory
workflowApplication.PersistableIdle = (a) =>
{
return PersistableIdleAction.Persist;
};
workflowApplication.Unloaded = (a) =>
{
instanceUnloaded.Set();
};
workflowApplication.Completed = (a) =>
{
instanceUnloaded.Set();
};
workflowApplication.Persist();
id = workflowApplication.Id;
workflowApplication.Run();
Session["id"] = id;
workflowApplication.Idle = (a) =>
{
instanceUnloaded.Set();
};
instanceUnloaded.WaitOne();
var bookmarks = workflowApplication.GetBookmarks();
if (bookmarks != null && bookmarks[0].OwnerDisplayName == "CC")
{
workflowApplication.Unload();
Context.Response.Redirect("SecondPage.aspx");
}
Context.Response.Redirect("FinalPage.aspx");
}
private static void SetupInstanceStore()
{
instanceStore = new SqlWorkflowInstanceStore(#"Data Source=xxx;Initial Catalog=SampleInstanceStore;User Id=xxx;Password=xxx;Asynchronous Processing=True");
InstanceHandle handle = instanceStore.CreateInstanceHandle();
InstanceView view = instanceStore.Execute(handle, new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(30));
handle.Free();
instanceStore.DefaultInstanceOwner = view.InstanceOwner;
}
This seems to work very well in that it persists the workflow to the database and if the bookmark is set I want to redirect to a second page for the user to enter more data.
This is the part of the code that I am having problems with: -
var bookmarks = workflowApplication.GetBookmarks();
if (bookmarks != null && bookmarks[0].OwnerDisplayName == "CC")
{
workflowApplication.Unload();
Context.Response.Redirect("SecondPage.aspx");
}
Context.Response.Redirect("FinalPage.aspx");
If there's a bookmark set, I redirect to an intermediary page, if not and no user intervention was necessary, the page will just redirect to the final page.
This works if the bookmark is set, but if not the workflowApplication.GetBookmarks() statement throws an exception telling me that the workflow has completed.
I can't seem to find a way to detect at this stage which state the workflow is in so that I can redirect to the relevant page.
Maybe I have the wrong idea in general, as much as I search though, I cannot seem to find a lot of guidance on this subject.
Any ideas?
Thanks,
Jim.
I don't think there is a way to directly determine if the workflow is completed from WorkflowApplication (except for catching and inspecting the exception that is thrown).
But you could set a flag in side your Completed delegate which is executed only if the there is no bookmark set and the workflow is completed. You could then check this flag before calling GetBookmarks().
Not sure if I understand exactly, but it seems that your page controller is looking at the state of the workflow to understand what page to redirect to? The problem is that the state may be non-existent if the WF instance has ended?
If the above is correct then perhaps the approach is wrong. A more appropriate approach might be to have a WCF WF service on AppFabric (correlated by session id) handle the website request directly. (If a user in a particular session visits the site, then the WF determines what page to render, and if the user hits a certain button, then send a WCF WF message using net pipe binding)
instead of
workflow.idle
you need
wfApp.PersistableIdle
and don't forget
instanceUnloaded.Set();

asp.net can you mix cookieless with cookie session stored session data?

Is it possible to use mixed cookieless sessions with cookie sessions?
I've an application that captured user details and then redirect for payment to an ssl page. I was wondering if this is possible?
http://www.mydomain.com/confirm.aspx
redirects to
https://www.mydomain.com/(S(za1tw2l2k02jer4fiskzlovd))/payment.aspx
Note: the session Id in the latter url.
So in essence, we use the standard cookie session for the majority of the application but when we transfer to an ssl page we pass the SessionId to the https url to pick up the session. I've tried this locally but it starts a new session.
Am I missing a trick?
Thanks
I've found a solution that seems to work
When transfering between http and https i've the following:
As you can see I'm passing the session id manually to the https page.
protected void btnPurchase_Click(object sender, EventArgs e)
{
// Confirm puchase code **
string sslPaymentPath = string.Format("https://{0}/payment.aspx?sid={1}", Request.Url.DnsSafeHost, Session.SessionID);
Response.Redirect(sslPaymentPath);
}
Upon reaching the ssl page, asp.net sees the request as a new session so I use the Start_Session method in the global.asax to abandon the newly created session and add a new session cookie with the session id passed in from the query string. Because the AquireSessionState which populates the session keyValue pair has already been run by this point I need to redirect the page back to itself to repopulate those values.
It seems to work really well :)
void Session_Start(object sender, EventArgs e)
{
bool isPaymentPage = (Request.Path.ToLower().IndexOf("payment.aspx") != -1);
// Code to load session over ssl. When changing between two sessions
if (isPaymentPage && Request.QueryString["sid"] != null && Request.IsSecureConnection)
{
string passedSessionId = Request.QueryString["sid"];
Session.Abandon();
Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", passedSessionId));
Response.Redirect(Request.Url.LocalPath, true);
}
}
Also with regard to somebody clicking on an external link whilst browsing the ssl purchase.aspx page i've written following in the global.asax to redirect traffic back to standard none ssl pages if it's not the payment page.
void Application_BeginRequest(object sender, EventArgs e)
{
bool isPaymentPage = (Request.Path.ToLower().IndexOf("payment.aspx") != -1);
// In the case someone has navigated away from the payment page redirect them back to the none secure protocol.
if (!isPaymentPage && Request.IsSecureConnection)
{
bool isAxdResource = (Request.Path.ToLower().IndexOf(".axd") != -1);
if (!isAxdResource)
{
string url = Request.Url.AbsoluteUri.ToLower().Replace("https://", "http://");
Response.Redirect(url,true);
}
}
}
Hope somebody finds this useful, I was stuck for a while trying to come up with a nice solution.
My inspiration came from this url.

Resources