How to prevent additional page requests after response sent - session

I have configured a listener on kernel.request which sets a new response with redirect when the session time has reached a certain value. The listener works fine and redirects to a certain page, on the next request, after the session has ended. But my problem is on the page I have many links and if I press multiple times the same link, the initial request with the redirect is cancelled/stopped and a new request is made with the last link pressed and so it passes my redirect even though the session has ended and is destroyed. So, my question is how to prevent additional requests/link presses after the firs request is made?
Here is my code:
public function onKernelRequestSession(GetResponseEvent $event)
{
$request = $event->getRequest();
$route = $request->get('_route');
$session = $request->getSession();
if ((false === strpos($route, '_wdt')) && ($route != null)) {
$session->start();
$time = time() - $session->getMetadataBag()->getCreated();
if ($route != 'main_route_for_idle_page') {
if (!$session->get("active") && $route == 'main_route_for_site_pages') {
$session->invalidate();
$session->set("active", "1");
} else {
if ($time >= $this->sessionTime) {
$session->clear();
$session->invalidate();
$event->setResponse(new RedirectResponse($this->router->generate('main_route_for_idle_page')));
}
}
} else {
if ($session->get("activ")) {
$session->clear();
$session->invalidate();
}
}
}
}
Thak you.

Idea #1: Simple incremental counter
Each request sends sequence number as param which is being verified as expected at the server.
Server increments the number and sends it back via response
the new number is used in future requests
Basically, if server expects the SEQUENCE number to be 2 and client sends 1 the request is to be rejected.
Idea #2: Unique hash each time
Similar to the idea above, but uses unique hashes to eliminate predictive nature of incremental sequence.

I resolved the issue using JQuery: when a link was pressed I disabled the other ones and so only one request is made from the page:
var isClicked = false;
$(".menu-link").click(function(e) {
if(!isClicked) {
isClicked = true;
} else {
e.preventDefault();
}
});
Thanks.

Related

Canceling request with browser.webRequest.onBeforeRequest also cancels previous pending tab requests

The following code is used in an add-on to cancel all main-frame requests and re-initiates them in a new tab:
browser.webRequest.onBeforeRequest.addListener(
filterRequest,
{urls: ['<all_urls>'], types: ['main_frame']},
['blocking']
);
function filterRequest(details) {
const match = details.url.match(/\/container$/);
if (!match) {
return {};
}
browser.tabs.create({url: details.url.replace(/\/container$/, '')});
return {cancel: true}
}
However, if the initial tab had a heavy web-page loading, it stops when the new request is cancelled. I thought that since the request is cancelled, it would be like it was never initiated, so that previous web-page would continue to load. Why is that happening and how can I allow the web-page to finish loading?
Save the created tab's id in a global list and check it at the beginning:
const tabIds = new Set();
function filterRequest(details) {
if (tabIds.has(details.tabId)) {
tabIds.delete(details.tabId);
} else {
browser.tabs.create({url: details.url})
.then(tab => tabIds.add(tab.id));
return {cancel: true};
}
}

Multiple ajax get requests of same route but different query string

I have had this for a couple of days now.
I have a simple search form. When form is submitted the server searches for some data from another server and return data to the screen. When the submit completes it gets some javascript from the server based on the results returned from the search. the javascript then makes multiple concurrent jquery get requests, lets say 4, to the asp.net mvc3 webapp.
I have demonstrated that all the get requests fire at the same time in Firebug but when debugging my app with VS the breakpoints only get hit once the previous request completes.
The actions are the same but the querys are different; ie
/Home/Details/040801
/Home/Details/040802
/Home/Details/040803
So these are different URLs and, from what i found out, FF should treat them differently.
So my questions are:
Am I missing something obvious?
Does IIS have some funny blocking on the same route?
Is it a session cache issue? I am locking lock (lockobject){} on writes to the common session variables.
Im not using ViewBag or TempData.
The page load times, even when everything is cached in the Session, are still noticeably synchronous.
Windows Server 2008 R2
Using IIS 7.5
ASP.NET MVC 3
VS2010 Chrome or FF browser
I have my routes set up as follows:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Home", action = "Index" } // Parameter defaults
);
routes.MapRoute("Details", "{controller}/{action}/{id}/{booking}", new { id = UrlParameter.Optional, booking = UrlParameter.Optional});
Nothing special there as you can see.
Sample code from one of the blocked routes:
public ActionResult Details(string id, bool booking = false)
{
if (booking)
{
return BookingDetails(id, true);
}
Dictionary<string, FlightDetails> detailDic;
string scenarioInput;
lock (DetailsLock)
{
if (Session["DetailDic"] == null)
{
Session["DetailDic"] = new Dictionary<string, FlightDetails>();
}
detailDic = (Dictionary<string, FlightDetails>)Session["DetailDic"];
}
if (detailDic.ContainsKey(id))
{
return PartialView("Details", detailDic[id]);
}
lock (GuidLock)
{
if (Session["DetailGuids"] == null)
{
Session["DetailGuids"] = new Dictionary<string, string>();
}
scenarioInput = ((Dictionary<string, string>)Session["DetailGuids"])[id];
}
// query results list
string queryText = string.Format("<View><Query><Where><Eq><FieldRef Name=\"Title\" /><Value Type=\"Text\">OUT {0}</Value></Eq></Where></Query></View>", scenarioInput);
ListItemCollection oList;
int counter = 0;
do
{
oList = SharepointHelper.GetListFromSharepoint("ListName", queryText, ClientContext);
counter++;
Thread.Sleep(1000);
} while (oList.Count == 0 && counter <= Timeout);
if (oList.Count == 0)
{
return PartialView("Details", (object)null);
}
var item = oList[0];
FlightDetails flightDetails = CreateFlightDetails(id, scenarioInput, item);
lock (DetailsLock)
{
detailDic.Add(id, flightDetails);
}
return PartialView("Details", flightDetails);
}
when using session object in server-side your async calls wait for session object released by other request. Becuase of this async ajax calls act like sync. You have to use session as readonly in that action.
Add this attribute to action you call if you dont write anything to session.
[SessionState(SessionStateBehavior.ReadOnly)]

Simple Login Attempt counter using MVC 3 and Ajax

Ok so this is driving me nuts. I am probably tired and the answer is looking at me.
public ActionResult _Login(LoginViewModel loginViewModel)
{
if (User.Identity.IsAuthenticated)
{
return JavaScript("window.location=" + "'" + loginViewModel.ReturntUrl + "'");
}
if (ModelState.IsValid)
{
if (Session["loginCount"] == null) //setup the session var with 0 count
{
Session.Add("loginCount", 0);
}
_loginStatus = _authenticationService.Authenticate(loginViewModel.SiteLoginViewModel.EmailAddress,
loginViewModel.SiteLoginViewModel.Password);
if(!_loginStatus.UserExists)
{
ModelState.AddModelError("SiteLoginViewModel.EmailAddress", _loginStatus.ErrorMessage);
return PartialView();
}
// This will only be true if the user types in the correct password
if(!_loginStatus.IsAuthenticated)
{
Session["loginCount"] = (int)Session["loginCount"] + 1;
Response.Write(Session["loginCount"]); // Counter is incremented twice!!!!
//_userService.SetInvalidLoginAttempts(loginViewModel.SiteLoginViewModel.EmailAddress, 1);
ModelState.AddModelError("SiteLoginViewModel.EmailAddress", _loginStatus.ErrorMessage);
return PartialView();
}
// DELETE ANY OPENID Cookies
var openidCookie = new HttpCookie("openid_provider");
if (openidCookie.Value != null)
{
openidCookie.Expires = DateTime.Now.AddDays(-1d);
Response.Cookies.Add(openidCookie);
}
_userService.SetInvalidLoginAttempts(loginViewModel.SiteLoginViewModel.EmailAddress, 0);
SetAuthTicket(loginViewModel.SiteLoginViewModel.EmailAddress, _userService.GetUserId(loginViewModel.SiteLoginViewModel.EmailAddress),
loginViewModel.SiteLoginViewModel.RemeberLogin);
if (!string.IsNullOrEmpty(loginViewModel.ReturntUrl))
{
return JavaScript("window.location=" + "'" + loginViewModel.ReturntUrl + "'");
}
return JavaScript("location.reload(true)");
}
return PartialView();
}
This almost seems that the request is being processed twice however when i step through with the debugger I only see it once. Please ignore the non important parts of the ActionMethod
This looks like you are tying to code for stuff that you automatically get with .Net's Membership provider.
Your first line "User.Identity.IsAuthenticated" looks like you are using part of membership provider but it would seem the rest is trying to code around it.
Also, why are you returning javascript to direct the user's browser to a new URL? Regarless of what .net platform you are on there are plenty of ways to redirect the user's browser without having to return raw javascript, which in my book is REALLY BAD.
##
This fixed the problem and will be removed rather than commented out. Including this twice is very bad obviously :)

XDomainRequest object caching/asynchronous call issue

I have an aspx page on which I am using XDomainRequest object to populate two div(s) with html returned from AJAX response.
I have used Jquery to get the divs and perform "each()" on the retrieved List
var divs = $("div");
divs.each(function(index) {
if (window.XDomainRequest) {
xdr = new XDomainRequest();
if (xdr) {
xdr.onload = function() {
alert("XDR Response - " + xdr.responseText);
var currentDivID = divs[index].attributes["id"].value;
var selectedDiv = $("div[id='" + currentDivID + "']");
if (xdr.responseText == '') selectedDiv.attr("style", "display:none;");
else selectedDiv.append(xdr.responseText);
};
xdr.open("GET", xdrUrl);
try {
xdr.send();
} catch (e) {
alert(e);
}
} else {
alert('Create XDR failed.');
}
} else {
alert('XDR not found on window object .');
}
}
Now, whats happening is , i have two Divs on a page that have different IDs and when this code runs on "$.ready(function(){})" , both requests are asynchronously sent to the server and processed
the result is
1. sometimes the onload get the response for the second div in both div results.
2. IE sents only one request to the server(I am using fiddler to see what requests are sent to server).
Can anybody guide me whats wrong with the code ? As far as I know XDR does not support synchronous calls, and asynchronous calls are giving me wrong results. Any workaround/tip for this problem.
Issue solved by myself when I pointed out a mistake in my code:(.
xdr = new XDomainRequest();
should be
var xdr = new XDomainRequest();
For Point 2 , I added "Cache-Control:no-cache" header in my response and it solved the matter.

Same Ajax is not working in IE more than one time

i my webpage when the user click forgot password button i ask email , Securitykey etc.. when the user click the sendmail button i send the email,securitykey, etc to a ajax function named 'sendmail(par1,par2,par3)' [Code is below]. The user provide Existing mailid , securitykey... , rtstr[1] is set to 1 [one] . So the 'Mail send successfully' was displayed . But if the user again enter the info [without refreshing the page]and click sendmail button, it didn't work in IE. But it works perfectly in Firefox.
var xmlhttp1;
xmlhttp1 = GetXmlHttpObject();
function sendmail(Mailforpwd, Secquestion, Secanswer) {
if (xmlhttp1 == null) {
alert("Browser does not support HTTP Request");
return;
}
var url = "SendEmail.php";
url = url + "?Email=" + Mailforpwd;
url = url + "&Squestion=" + Secquestion;
url = url + "&Sanswer=" + Secanswer;
xmlhttp1.onreadystatechange = stateChanged;
xmlhttp1.open("GET", url, true);
xmlhttp1.send(null);
function stateChanged() {
if (xmlhttp1.readyState == 4) {
var Result = xmlhttp1.responseText;
rtstr = Result.split('#');
//alert(xmlhttp1.responseText);
//alert(rtstr[0]);
//alert(rtstr[0]);
if (rtstr[0] == 1) {
document.getElementById("Errorcredentials").innerHTML = "Mail send successfully";
}
else if (rtstr[1] == 0) {
//alert(document.getElementById("Errorcredentials").innerHTML);
document.getElementById("Errorcredentials").innerHTML = "Please provide Exist information";
}
else {
document.getElementById("Errorcredentials").innerHTML = "There is a problem in sending mail, please try after sometime";
}
}
}
}
function GetXmlHttpObject() {
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
return new XMLHttpRequest();
}
if (window.ActiveXObject) {
// code for IE6, IE5
return new ActiveXObject("Microsoft.XMLHTTP");
}
return null;
}
Here my problem is at second time the function stateChanged() was not called , if i put a alert in this function , first time it display alert box , But next time it won't. This is my problem . The sendMail.php was called eachtime .
Whenever I have this problem it is because IE caches your AJAX request. The best way to avoid this is to append a random number as a key in your query string each time.
url = url + "&rand=" + Math.random();
Or, better, since your AJAX request appears to be causing some action to happen server-side, why don't you use HTTP POST instead of GET?
xmlhttp1.open("POST", url, true);
This is a caching problem. Append current date time to your url to make it unique.
url = url + "&rand=" + (new Date());
just swap these lines in your code.
xmlhttp1.onreadystatechange = stateChanged;
xmlhttp1.open("GET", url, true);
after fixing it looks like
xmlhttp1.open("GET", url, true);
xmlhttp1.onreadystatechange = stateChanged;
thats it!!
skypeid: satnam.khanna

Resources