We are using Sharepoint 2007
We initialising the session variable on page load
We have one javascript function as mentioned below
function backclick()
{
__doPostBack('btnCaseSearch', 'Click');
alert('Select the Search Criteria.');
}
but after calling this we are losing session value.
If we remove __doPostBack('btnCaseSearch', 'Click');
then alert is displaying each time when page gets load but session is not losing its value.
How to maintain session pls help or suggest some alternative to _doPostBack()
the sceneario is like this
below javascript function
function backclick()
{
__doPostBack('btnCaseSearch', 'Click');
alert(result not found.');
}
function check()
{
var btn ="<%=Session["search"]%>";
if(btn == "true")
{
do something
}
else
{
else part
}
Below server side code
Page_Load()
{
//initialise session variable
session["search"] = "true";
}
btnSearch_click()
{
if(result not found)
{
this.Page.ClientScript.RegisterStartupScript(this.GetType(),"page_index_script1", "backclick();", true);
}
}
so when backclick() javascript function gets called at that time session is losing its state but if backclick() doesn't get called then code works perferctly
Thanks
Something which jumped out at me:
We initialising the session variable on page load
Is this page load server-side?
Each time you _doPostBack will cause pageLoad to execute, so I believe this is where you're overwriting your session variable.
The only way the session will loose it's state is:
If it gets overwritten or removed (use a breakpoint to check you're not setting it twice!)
The browser is not surrendering the cookie on subsequent requests
Check both of these and if your problem isn't solved post what you found.
Related
MVC noob here.
I currently have this code that fires off my HomeController when a page loads via AJAX:
namespace ETTData.Controllers
{
public class HomeController : Controller
{
[HttpPost]
public ContentResult clearSessions()
{
var currentSession = System.Web.HttpContext.Current.Session;
System.Diagnostics.Debug.WriteLine("BEFORE: " + currentSession.Timeout);
currentSession.Abandon();
//currentSession.RemoveAll();
//currentSession.Clear();
System.Diagnostics.Debug.WriteLine("AFTER : " + currentSession.Timeout);
return new ContentResult { Content = "OK", ContentType = "text/plain" };
}
}
}
The output of the debug.WriteLine is:
BEFORE: 35
AFTER : 35
So as you can see it has 35 on the BEFORE but also has 35 for the AFTER when it shouldnt equal anything since I used currentSession.Abandon(); prior to calling that output.
I am setting the session timeout via the Global.asax.cs file:
namespace ETTData
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Session_Start(Object sender, EventArgs e)
{
HttpContext.Current.Session.Timeout = 35;
}
}
}
So saying all that - I'm at a loss as to why its not clearing the session...
Yea that's a good one that got me too in WebForms a long time ago.
The issue is, that your session is bound to a session cookie.
The cookie is transmitted in the request and response headers, which means via the HTTP protocol. The HTTP protocol is stateless, and therefore, it can't remove a cookie until after a response has been sent.
When you call session.Abandon, the session data will be abandoned at the same time as the cookie is abandoned at the client. Which means the frameworks marks the session data as "to be cleared after the response has been sent", which is after response.end. At response.end (which will be called after ContentResult.ExecuteResult), the framework will then clear the session. Subsequently it will call the Session_End event.
Session.Clear removes items immediately, but it will not remove the session cookie - therefore it also doesn't end the session, and it will not call the Session_End event - which is because it doesn't expire the session cookie.
Think of it as async-function.
You called abandon, but it's not yet executed.
As the others told you, if you need the session cleared immediately, call session.clear after session.abandon.
But if you start another session after you called session.abandon, you'll run into a very sharp knife.
Basically, you should never use sessions.
If you want to access "session" data without a detour into the database, you should store the information in an encrypted and asymmetrically-signed cookie, which you can bind to a session-lifetime, if you want to, but you don't have to. Google JWT for more information. I would bind such data into your auth-cookie. That way, there's no need for >1 cookies. The default timeout of 20 minutes in ASP.NET is a pretty bad thing. Your session data shouldn't expire until your authentication has.
Also, be careful what you write into your session.
If you just store user information there, that's fine.
But if you store state information there, you'll have a problem, because I can open multiple tabs of your site at once, and then the state from tab2 will overwrite the state of tab1. You have ONE session per domain, not one per tab.
Have a look at this question to find your answer.
In Short: Session.Abandon destroys the session but doesn't clear it's values. This happens when the request ends. Session.Clear clears everything from the session but doesn't destroy it.
I wanna free some DB resources and set few flags when User Session Ends in ASP.NET Site. But when I write my code to access session variables in Session End method of Global.asax file, its getting called everytime the App starts, Why this weird behavior?
Secondly, I want to access user specific session variables and free them up in DB on Session End. Thus I am using few session Variables where I am setting them in a webmethod on a Page and trying to access them on Session End. But since Session end is being called on App start up its always throws Null reference exception.
Here is mycode. for Setting up a variable in Webmethod in a .aspx page
[WebMethod(EnableSession=true)]
protected void checkUser()
{
Session["TestObject"] = "Hello I am session";
}
In my global.asax file I am trying to access as follows in Session_End method
void Session_End(object sender, EventArgs e)
{
// Code that runs when a session ends.
// Note: The Session_End event is raised only when the sessionstate mode
// is set to InProc in the Web.config file. If session mode is set to StateServer
// or SQLServer, the event is not raised.
if (this.Context.Session != null && this.Context != null)
{
string k = this.Session["TestObject"].ToString();
}
}
I even tried HttpContext.current.Session etc.. but none worked. All are throwing exception as Session end is called on App start up and even when session timed out.
I have over 30 aspx pages, i have discovered a problem recently that if i did any kind of database transaction like insert, update, delete and then after the transaction is complete i pressed F5 or refreshed the page in anyway the same is transaction occur.
I searched for a solution but all i could found is that i have to check for viewstate on each button which is impossible, cause that means there will be a lot of work. There got to be generic solution, please help me in this problem.
Edit:
Here is the code on one of the buttons which change a value in data base to either true or false:
protected void btn_Publish_Click(object sender, EventArgs e)
{
if (Convert.ToBoolean(int.Parse(hf_Published.Value.ToString())))
{
publish(false);
}
else
{
publish(true);
}
}
After the execution of the code if refreshed the page the same code is executed, i noticed that since a break point was placed on this method.
You can try this. I used this in several project and working successfully.
public bool IsRefreshed
{
get
{
if (Convert.ToString(Session["RefreshTimeStamp"]) == Convert.ToString(ViewState["RefreshTimeStamp"]))
{
Session["RefreshTimeStamp"] = HttpContext.Current.Server.UrlDecode(System.DateTime.Now.ToString());
return false;
}
else
{
return true;
}
}
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
ViewState["RefreshTimeStamp"] = Session["RefreshTimeStamp"];
}
protected override void OnLoad(EventArgs e)
{
if (!Page.IsPostBack)
{
Session["RefreshTimeStamp"] = HttpContext.Current.Server.UrlDecode(System.DateTime.Now.ToString());
}
base.OnLoad(e);
}
There IS a generic solution, used for years by thousands of developers.
And the solution is: each time you perform an intrusive process at the server (insert/update/delete) you don't just render the page but rather you redirect the response with 302 to a fresh page with "your transaction succeeded" message.
This way, pressing the F5 will just refresh this message page, not the original page which triggers the transaction.
It is up to you whether or not this is directly applicable in your scenario.
http://en.wikipedia.org/wiki/Post/Redirect/Get
To fix this issue you could check the following:
Disable the submit button when necessary
Add some validation to your code and check for double entries
Redirect the user to another page after submit
Unless it's a real 'transaction' like payments etc. (which others already explained, do redirect etc.),
You could also try defining caching on your pages that interact with the Db or are bottlenecks for your app.
If you wanna have always live info (and it's that 'alive' type of app) then no luck with that solution (but even then), but usually, you can put some reasonable time expiration on how 'fresh' you want your data to be.
Caching ASP.NET Pages
I am in a bit tricky situation. I am using JavaScript's PageMethod functionality where I am invoking a PageMethod which works like a gem. However I am having an issue in accessing the HttpContext's state which returns me a value "SYSTEM" for
HttpContext.Current.User.Identity.Name
which is not the actual current User Name.
I know there are couple options like storing HttpContext.Current in a Session or saving Context's state in some other custom container but given a web farm environment I am assuming that this will not work as expected.
Here is the code I am working on with
function MyFunction(){
PageMethod.MyPageMethod();
}
here is the signature of the server method
[System.Web.Services.WebMethod()]
public static void MyPageMethod()
{
// gives me "SYSTEM"
var user = HttpContext.Current.User.Identity.Name;
}
Also if I use the above code to access user name in OnLoad event of the page then it works fine and returns me the CurrentUserName.
I am trying to get the above code to work in an ASP.NET Webform... :)
So I am wondering if there is a way to access the current actual user in page methods without making use of sessions.
Any help will be deeply appreciated.
NiK...
After quite some reading I think I was trying to do something which is not correct as to how page methods work. It gets quite tricky when your application's authentication system is windows based and these page methods when you invoke from JavaScript will not cause a postback and do not invoke the HttpModules. Instead it just calls that page method.
FYI, we had our own custom HTTPModule to handle security.This is even before any other HttpModule occurs and this was not being invoked while calling the page method as we are not doing a postback or even a partial postback (so the whole "niche" of a HTTPPost was missing). Moreover this led to a conclusion that we were making service calls without any authentication and was potentially a big security issue for us.
The bottom line is it was a bad design, well having said that I would like to mention about the solution/workaround we came up with and here is what we did. So, the only option we had is to do a postback keeping the UI alive and we wanted to update a label's message asynchronously and we achieved it by doing a hack using Sys.Application.add_init.
<script language="javascript" type="text/javascript" >
Sys.Application.add_init(function() {
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequest);
});
function beginProcess() {
processCurrentItem();
}
var currentItem = 0;
function processCurrentItem() {
if (currentItem < 5) {
currentItem = currentItem + 1;
__doPostBack('updatePanel', currentItem);
}
}
function endRequest() {
processCurrentItem();
}
</script>
The markup we had in place was pretty simple with a label in the update panel and a button that invokes the "beginProcess()" function. Finally in the OnLoad we had the following code in place
protected override void OnLoad(EventArgs e)
{
if (this.IsPostBack)
{
this.lblLabel.Text = "text you may wanna update with";
// Call the Method you may wanna call
// also you may use Request["__EVENTARGUMENT"] to know who caused the
// postback and Request["__EVENTTARGET"] to access the argument you may
// have passed in.
}
}
And this solution is no longer using the JavaScript Page methods. And based on this solution if anyone thinks I am missing something here or think there is any other other way of doing this then do update this post with your suggestions.
NiK
When I want to redirect a user who has lost session state back to the StartPage I find Response.Redirect("~/StartPage.aspx") causes the error "Response Redirect Cannot Be Called In A Page Callback". Therefore in a Page.IsCallback situation I want to add javascript to do the redirect - this works - see code below.
protected void ForceBackToStartPage()
{
if (Page.IsCallback)
{
string fullLoginUrl = ConvertRelativeUrlToAbsoluteUrl( "~/StartPage.aspx" );
string script = string.Format("window.location.href = '{0}';", fullLoginUrl);
ClientScriptManager cm = Page.ClientScript;
cm.RegisterClientScriptBlock(GetType(), "redirect", script, true);
//Response.Flush();
//Response.End();
}
else
{
Response.Redirect("~/StartPage.aspx");
}
}
After I have added the javascript in this section the code continues to process normally leaving this function and going off to other processing sections of the webpage - probematic as the user has no session data. Ideally I'd want processing of this web page to finish - and for the page to return in a valid state so that the user gets redirected.
Is this possible?
I thought Response.Flush(); Response.End(); might do the trick - but the webpage sent back to the browser causes XML Parse errors.
Further info: I check for missing session data in a few places (depending on the webpage - this code is in lots of web pages) - for instance - PageLoad and from some submit button methods.
Before the new method I used this code e.g.:
protected void Page_Load(object sender, EventArgs e)
{
if ((string)Session["OK"] != "OK")
{
// the session has timed out - take them back to the start page
Response.Redirect("~/StartPage.aspx");
}
...rest of processing
Now it's invoked like this:
protected void Page_Load(object sender, EventArgs e)
{
if ((string)Session["OK"] != "OK")
{
// the session has timed out - take them back to the start page
ForceBackToStartPage();
}
...rest of processing
so I could obviously use
else
{
...rest of processing
}
but I was hoping not to have to do that as SVN Source Control takes that to mean I've re-written the whole 'rest of processing' section. This is problematic as when I merge from a branch into the trunk it does not check I am not overwriting mods because it assumes it's all new code coming in.
Response.Redirect issues a "302 Moved" command that cannot be served asynchronously. Given that you're just registering a script when IsCallback=true, could you not also do it when IsCallback= false? Register a script that hooks up an event to the loaded event of the window and redirect the page from script instead of from the server.
I was thinking about this again recently and realised the very obvious answer. Forget nicely structured code, as being part of an error trap this is a special case, and use a return; after the 'ForceBackToStartPage' method invocation:
protected void Page_Load(object sender, EventArgs e)
{
if ((string)Session["OK"] != "OK")
{
// the session has timed out - take them back to the start page
ForceBackToStartPage();
return;
}
...rest of processing
}