I have a simple ASP.NET MVC application. When the first action method is run it stores some data in the Session variable. On the resulting view I have a jquery ajax call triggered by a button to another action method.
When I click the button a different session id is used at the server side, it's a bit random. There is sometimes a gap of a second or so between starting and clicking the button and the Session ID still changes. This breaks the app as it tries to retrieve the data stored by the first action method.
Any idea what's going on? Both requests are to the same URL.
I see method one instantiate a new session with Id X and store the data.
Immediately after loading the Jquery request fires. I see a different session cookie id on the request header.
I get an error "data not found"
Many thanks,
This is by design and ASP.NET tries to be efficient in storing sessions for users. Remember unless you store anything in session the session value changes.
If you want to tell ASP.NET that you want it to track user sessions, you can do one of 2 things:
Store something in the session.
Simple handle the Session_Start event in your GLobal.asax. The presence of this method will tell ASP.NET to track sessions , even if there is no data in the session..
// NOTE: There is no need to add any thing to session if you are doing this...
public void Session_Start(object sender, EventArgs e)
{
}
This behavior had caused me much worry in the past :)
Are all your AJAX calls using the same server name:
http://localhost/whatever
vs
http://machinename/whatever
Related
I don't understand the notion of session for webservices. In one hand you can allow session in DataAnnotation like that :
[WebMethod(EnableSession = true)]
In the other and you can configure the session state in IIS :
So I put Session State in process and set the delay for 20 minutes.
Then in my webservice I try to get the session ID like that :
return HttpContext.Current.Session.SessionID
I use a winform to get this information and call the webservice.
And the session ID Change at every call. I don't understand why, beaucoup SessionState is set to 20 minutes...
May I'm in wrong way ? Can you explain me ?
Is SessionID correspond to the Session State in IIS ?
There must be something that connects the request to a particular session. Usually a cookie is used for that. This cookie is sent along with the response, so the calling application must remember that cookie and send it along with the next request. Without cookie the request is handled as if it's a new session.
A browser handles this by default (unless specifically switched off), for an other application you need to do cookie management yourself. For this you need to use a single CookieContainer that will be shared among your requests.
See the link in the answer by Marius for more details.
I was thinking of a solution, but then I found this post :
How to keep session alive between two calls to a web service in a c# application?
I hope this helps.
If you want to keep your sessionID same througout users session life time you should add a global.asax file to your web project and implement Session_Start method.
Please check this link:
https://msdn.microsoft.com/en-us/library/system.web.sessionstate.httpsessionstate.sessionid.aspx
I have a strange problem in ASP .NET MVC 4. In AccountController I am doing redirects on certain actions and put data into TempData (which is stored in Session) before that:
[AllowAnonymous]
public ActionResult Activate(string token)
{
new CustomSignupService().Activate(token);
TempData["Message"] = "User was successfully confirmed";
return RedirectToAction("Message", "Home")
}
Now I know I could just return shared Message view in this case, but this is just a code sample to reproduce the problem.
CustomSignupService.Activate does a db lookup via NHibernate and updates user in transaction (user activation). Sometimes (lets say 1/5 tries in 5 minutes) TempData does not make it throught the redirect, so I added logging into Session_End and noticed that session ends when RedirectToAction is invoked. Right after that Session_Start is invoked but of course TempData is gone.
Session has default timeout (20min) and controllers use SessionStateBehavior.ReadOnly
Any ideas?
UPDATE
Step 1: It's not Application Pool recycling (I turned on all General Recycle Event Log entries on Application pool and checked event log, after session restarts but recycle is not causing it)
I had a problem with Session being lost. I used Fiddler and noticed that there was a duplicate ASP.NET session cookie with a blank value. I don't know how it got there. So a new session was created on every request. I deleted that duplicate cookie and the problem was solved.
Other unlikely reasons are:
IIS process recycle
Session.abandon being called
modifying bin folder or web.config causing app restart
Check out this page:
Losing Session State
I don't know ASP.NET MVC but in the dark centuries I used ASP.NET without MVC. I struggled several times with unexpected session ends. Most of the time it was caused by some simple things which are described in the article http://www.c-sharpcorner.com/uploadfile/technoNet/session-timeouts-causes-and-remedies/
Sometimes the server has entries in the event log that gives you a little bit more information.
And some other solutions might be
ASP.NET Session ending abruptly
random IIS session timeout
This is true with any other functionality present on the page. I don't want the last event that happened before post back to happen again.
I believe you should take a look at the PRG Pattern (Post/Redirect/Get)
Post/Redirect/Get (PRG) is a common design pattern for web developers
to help avoid certain duplicate form submissions and allow user agents
to behave more intuitively with bookmarks and the refresh button
In ASP.NET:
POST - Submit button click causes HTTP POST
REDIRECT + GET - HttpResponse.Redirect()
MSDN, Redirecting Users to Another Page
In server code, you can programmatically redirect by calling the
Redirect method. The method sends a command to the user's browser that
causes the browser to issue an HTTP GET command for the target page.
Few important notes regarding PRG pattern:
!!! The PRG pattern cannot address every scenario of duplicate form
submission. Some known duplicate form submissions that PRG cannot
solve are:
if a web user goes back to the web form and resubmits it.
if a web user clicks a submission button multiple times before the server response loads (may be prevented by using JavaScript to disable
the button after the first click).
if a web user refreshes before the initial submission has completed because of server lag, resulting in a duplicate HTTP POST request in
certain user agents.
if a malicious web user submits the form twice despite client-side safeguards and typical browser behavior.
You should learn about the PRG (Post/Redirect/Get) pattern:
Post/Redirect/Get (PRG) is a common design pattern for web developers
to help avoid certain duplicate form submissions and allow user agents
to behave more intuitively with bookmarks and the refresh button.
Source: http://en.wikipedia.org/wiki/Post/Redirect/Get
Basically you'll want to redirect via a GET request after the user has done a POST.
you can check already exist condition before inserting record in Database.
like in stored procedure you can check
if not exists (select id from table where column name ='test' )
begin
inser statement..
end
This is about PRG. The simple way to avoid this is redirect user to same page again:
Page: Update.aspx
void btnUpdate_click(object sender, EventArgs e){
// do your update here
Response.Redirect("Update.aspx");
}
This will create a redirect-header in Resoinse and browser will create a GET request to Update.aspx page. And if the User refresh the page, a GET will be sent. Look:
User submit the form : POST
Server do updates, return a redirect-header
Browser receives the response as a redirect-command : REDIRECT
Browser sends a GET request for same page to server : GET
Browser receives the response answered by a GET
If user refreshes the page: Browsers last command was GET, so will not fires a submit again
A simple way is to use javascript to disable the button when the users click it.
A way I use to avoid refreshes when high security is needed, is the use of a small "token" in session.
Let's say, we put a small 32 bit integer in our session.
The page will contain an hidden input containing our small integer token.
Each time we receive the page request, we increment that token by one, and, before doing so, we check for equality with the one received in the request.
If they match, it is not a refresh.
If they don't match, it is a refresh.
This will also block attempt to do back and next with browser buttons.
Of course at the point that token don't matches, the page should change or you'll have again the refresh problem.
It should show something like "hey, refresh back or next not allowed, press here to continue".
For increased security, you can xor that integer with a costant value dependant for example on some other value that is constant in session.
I have a .net c# web forms in my web application. I do some processing in the code behind of this page.
Within the mark up of this page, I have a http handler referenced, which outputs a response type of text/javascript, included in the markup:
<script type="text/javascript" src="handler.axd"></script>
I want to pass from my page to the http handler some values. I do not want to pass it via query string and session is not available to me.
Any ideas or tips as to how I can pass data/variable values from my page to the http handler?
I do not want to pass it via query string and session is not available to me
Cookies? In your main page set a cookie, and in the handler read the value of the cookie.
If this is not an option for you how about Application State? In your main page generate an unique GUID and store the value you would like to pass to the handler into the application state. Then pass the GUID to the handler as request parameter. In the handler use the GUID to fetch the value from application state.
If application state is not an option for you how about database state (or some other persistent storage mechanism on server)?
If all those are not an options for you describe your scenario in more details as I am afraid that you could quickly run out of options :-)
I know you don't want to use qs variables, but you could do the following. Create a unique key on page load, store your variables in Application Cache by that key, and stick that key as a querystring variable on you script reference, then access that information from Application Cache again. This is assuming that you're concerned about security or data size as the reason for now sticking directly in the querystring.
Have you looked at the HttpContext.Items collection?
Is it possible to postback to the server, perform a function, and then continue that postback on to an external place? (ie, to a payment system)
(the scenario is clicking a button to place an order, mark it as sent, then send them off to the payment page (there are form variables that needs to be sent to the payment screen as well))
You can (probably) use Response.Redirect and send the posted variables to the external page as part of the querystring.
The variables will then be visible in the browser's address bar, but this is no less secure than posted form variables, just a bit uglier.
You need to ensure that the variables are tamper-proof regardless of how they're submitted to the payment page. You should consult the payment provider's documentation to figure out how to do this.
Instead of thinking "continue that postback", if you want to send these values to a payment page, you can store them in session state and access them on that payment page. It's not a "postback" if you're transferring control to a different page.
UPDATE
Since it's Worldpay payment service, you need to check their API and perhaps contact them.
Securely submitting form data to Worldpay using ASP.NET
Google Search on ASP.NET and Worldpay
Similar question on SO
Yes, you could do that. Once the postback loads, output an HTML form that occurs outside of the default ASP.net form, and use javascript to automatically submit that form once the page has loaded.
You could do this entirely as a javascript solution (and update the div outside the asp.net form) or you could overwrite the rendering method of the page itself.
A work around if the two are on different page. This is just skeleton
try
{
Response.Redirect(To your order page);
Process your data
try
{
Response.redirect to WorldPay
Do Payment
}
catch
{
to original page
}
}
Catch
{
Reposne.Redirect to origin page
}
I'd try to use the URL API to accomplish this. I'm not sure if this is the right part of the API though.
http://www.rbsworldpay.com/support/kb/bg/htmlredirect/rhtml.html#rhtml5207.html
Edit: I see they are passing the price on the query string. Hopefully that's not susceptible to manipulation....