I have an ASP.NET (C#) page that has a long load time (like 2 minutes). The user is presented with a little animation and a "please wait" message. If the user accidentally loads this page, they need to wait for it to load.
My question is: Is there a way to stop the page load?
Thank you
If you want to stop the server side processing then its a tricky operation. Generally once a request is made that page is rendering on its own independant of other thigns going on. What you would probably need to do is re-engineer that page to check at regular intervals whether a stop command has been issued and abort whatever it is doing at that point. The stop flag could be put in session and should be cleared out after the stoppage.
You may also need to consider how to properly identify the right one to stop (in case there is more than one running). This could be done by returning a unique ID that can be used in part of a call to the "abort" page.
My approach though rather than this complciated rigmarole is to make efforts to stop the user from making this accident. Possibly make whatever link they are clicking pop up an alert saying "the following page will take several minutes to render, do you wish to continue" and then hopefully you will effectively be aborting the page request before it is even made.
I should note that I've never tried to do this sort of thing before so there may be easier ways to do it but this is how I'd probably think abotu going about the problem.
Try window.stop() in JavaScript.
Related
What might be the best way to implement timed-task in a web-site (asp.net) environment ?
Say clicking a button locks it for 4 hours, or a day. How would I go about implementing the process of counting those 4 hours, (or 1 day) and then unlocking the button) ?
Keep in mind this is a web-site: Do I
save the current datetime stamp to the DB (I'm logged in as a registered user to the web-site)
every time I visit the page with the button I retrieve the stamp and the duration
and calculate how much longer I have to wait, until the button is unlocked.
(And possibly implement a JS (for example) count-down counter that would show near the button)
I'd assume using session variables or cookies is a bad idea, as I may close my web-site or delete my user data and thus loose the above.
Since your requirement is to support this across sessions, then it definitely needs to be in the DB.
DB
Add a LockedUntilUtc column that indicates the date/time that the button should unlock. Better yet, name the column to represent the business model. Maybe you are writing an HR app the has a raise approval process, and there is a mandatory 7 day waiting period before the manager can release the raise to allow HR to review, and the button is laballed "Publish Raise" in which case I'd name it something like PublishRaiseAvailableUtc.
I've dealt with lots of scenarios like this, and it's often simpler to use the date/time that an event needs to occur. As opposed to saving the beginning of the timer and always having to add 7 days everytime you need to make a calculation.
UI
Send this value down with the page as a hidden value. Write javascript using the framework of your choice, or just something as simple as setTimeout which will fire to unlock the button at that point in time.
Do not worry about trying to come up with a convoluted way to prevent the user from unlocking the button by manipulating the HTML. You should assume they can unlock the button if they put effort into it. Given that assumption, we need server side logic to validate the request.
Server Post Validation
When the user clicks the button, and the POST is sent to the server, then server-side code should retrieve the value of PublishRaiseAvailableUtc from the database(do not trust the value posted from the hidden field), and compare that to the server time. I.e. server time should be greater than the PublishRaiseAvailableUtc, assuming you ensure you are comparing UTC times.
I think the best way is saving the day when the button becomes unlocked again. And every time the page is loaded, retrieve that info from the db to check if it should be locked or not.
Another possible way is to use an application variable. But i dont recommend this, because data is stored in memory and because if you reset the app or server, data will be lost.
You first problem is in your approach. You don't necessarily care how long it will be until the time you've saved, but you definitely do want your button to change when that time comes.
What I might suggest is to load the DateTime value from the database, place it somewhere in the page where JavaScript can read it. Now, one only problem is that some users may be able to locate and modify this value to skip the timer. I'm not personally familiar with a way to circumvent this easily, but you should be able to research a solution.
Once you have the value readable by JavaScript, a loop is probably going to be your best bet for checking the current time against your saved time, then performing whatever action you want.
A do..while loop will probably suit your needs
To avoid performance issues, use setTimeout to delay each loop iteration. The delay doesn't have to be very significant.
In the loop, retrieve the current date and time, then compare it to the date and time you saved in the database. If the current date and time is greater, perform your action.
Now, my idea may not be optimal, but I feel it is at least a step in the right direction. I also suggest a loop so that the user is not required to refresh the page to see what changes resulted from the performed action.
Do not rely on client side validation that the button is locked/unlocked. Always check server side that the click happened during the allowable time. This would prevent someone from "hacking" the page to allow a click outside of the allowable window.
I have a new message page that can only be accessed if you are replying to a message or you click to message a user (unless of course you guess the URL). The cancel button currently will send you back to the previous page you were on using javascript:history.back().
I'm wondering if this is the best practice or if I should be using something on the server side to set where the cancel button takes you.
I took a look at this similar question: Does using javascript:history.back(); have any unknown issues?
I don't understand the cache problem mentioned in that post or the javascript being disabled because the site has a lot of javascript that this feature would be the least of the concern if the user does not have javascript. I'm also not too worried about the user not having a page to go back to because as I said, this new message page can only be accessed by clicking on a button on a site unless you guess the URL or copy the URL into a new window.
I'm wondering if there's any other issues on doing it one way or another.
Thanks!
Well, one issue you did mention was when the user types in the URL? Maybe we're crazy, and/or hate buttons! Joking aside, using history.back is mainly frowned upon due to its static nature (who knows if there is a page to go back to).
What the guy is trying to say in the link you provided about caching is that, for example, say you had a sign in page. If you hit your button using history.back, the browser would use a cached version of the webpage, and in turn, clear out anything you filled in. It would also show that you weren't logged in on the users end.
If you do have server side logic. I think your best bet in this case would be to just put in an windows.location.href to your previous page. That way, this issue is resolved, and you know exactly where the user is going.
In my C# code, I am using Watin to navigate the web, to log in to a page, I need to click the log in button, but right after I want to log out, so I have the click log out button right after, but the log out part doesn't work. I even tried closing the browser (using the close method) after logging in, but it didn't work. It feels like as soon as the page gets changed (i.e. after logging in) no more commands from the c# will work.
Does anyone know whats wrong?
As mentioned in another answer Thread.Sleep(milliseconds) is a way to wait for a time period for something to load. Very, very easy to implement, but it is far from optimal due to varying load times, and if you make it long enough so that it will always wait long enough you'll end up with a lot of wasted time. On one test this is not a big deal, but for instance if you have to wait 5 seconds and you have 1000 tests.... etc etc etc.
The route I've gone is:
Put in Thread.Sleep()s to determine if it is a "wait" issue.
If the the code with the Sleep() is going to be used more than once figure out what is causing the need for the sleep().
Refactor out the Sleep() using various Wait...() methods. WaitTilExists, WaitForAttributeEqualsWhatever, WaitForAsyncToFinish <- Not real methods, but WatiN has a bunch built in
The big cause of waits for me now is JQuery asynchronous calls in ASP.NET and I made a static helper class that works well for me to wait for async calls to finish. These tend to be very specific to what framework(s) the sites you're testing are written in.
The watin click command wait until the browser is loaded so practically it wait for the postback.
In case if you using ClickNoWait() command it will not wait.
So if your code looks like this it should work:
browser.GoTo("www.your-site.com");
// fill user/pass
browser.Button(Find.ByClass("login-class")).Click();
browser.Button(Find.ByClass("logout-class")).Click();
In case it's still not working you can add this after login click browser.WaitForComplete();
In Watin you will encounter many situations where the code is non blocking (you'll execute a line of code and will immediately keep going) so for those cases you'll need to find a different way to know that the next page (action, etc.) is already there. For example, on a login page you could check if that pages has a TextBox called UserName:
<code>
TextField uName = browser.TextField(Find.ByName("userName"));
if(uName.Exists)
{
// Then do the login code....
}
</code>
In the same way you should control that the page after the login is there before you keep going executing your code. So for example, if you are logging in into a page that you know that will contain the text: "Your Account Details" you might do something like this:
<code>
browser.GoTo("http://www.yourdomain.com/login.aspx");
//do your login code
browser.WaitUntilContainsText("Your Account Details", 240); // the second parameter indicates the seconds it will wait before it times out.
// your code to deal with the page after the login.
</code>
Using Thread.Sleep is a recipe for confusion and that's a problem for sure, you will NEVER get the timing right with a web page (even if you think it will take 10 seconds it might never come back and at that point the server will be terminating the opened connection).
Hope it helps.
Use Thread.sleep in your scripts to sync with logout and login...
or
instead of logout you directly close application and use ie instance to relogin to application
I am trying to code an app for work where our clients can edit certain fields. When they click edit, the code will lock the data to be editted. And when they click save the data will unlock. But I am having trouble deciding if I can unlock the data when they click elsewhere, go to another page or site, or even close the browser.
What's a good way to decide if the user has left the edit page?
(We are using C# .NET 3.5 and JQuery and a SQL Server 2005 DB).
If you really must use pessimistic locking you could add check in Session_End and unlock all locks that this user set in current session. Use onUserExit jQuery plugin to end session if user closes the browser window or goes on another site, here is the example :
https://stackoverflow.com/a/10481972/351383
You can make use of "onunload" event of html tag. This event is raised
- when Page is closed using X button
- when Page is redirected(In your case user clicks on edits and move on to different link without saving.)
Hope this helps!!
Your question is being understood as "what's a good way to decide if the user has abandoned the edit page without having clicked 'Save' to unlock the field?"
But I am having trouble deciding if I can unlock the data when they click elsewhere, go to another page or site, or even close the browser.
All the scenarios in which someone looks at another page from the same application might mean another window in the same session - perhaps to check something. You don't want that to trigger an unlock because your user could still have a window open in which they can submit the edit.
The other scenarios where the user leaves the page can use onUserExit.
However, you omit from this list the scenario "user goes to lunch leaving webpage open". This is why pessimistic locking is problematic.
Therefore, rephrase the problem as "the user has clicked Edit, but then failed to make the amendment and save within a reasonable time limit".
Basically, your lock should at some point expire.
Upon clicking 'Edit', the save lock kicks in and a timer (5 minutes?) starts, which is also visible on-screen. (If getting these in sync is an issue, make the client-side timer shorter than the server-side one). Your users must make the change and click Save within this time. You could perhaps add an Extend button to extend the time.
The principle is that you need to determine that someone has left it too long, not that someone has left it. You also show to users that having clicked Edit you are expecting them to make an edit some time soon.
You will need to code your system to unlock fields where the lock has expired.
This has the benefit that your countdown will look 'cool' to the sorts of people that request such edit locks.
I have an asp.net page
when Loading this page it creates a Thread to do some thing
My Question is :
How to kill this thread when the user close the page ?
I have tried with "onUnload" event
but it just works with javascript function (as I know)
and we can't use asp.net code in javascript function
Do You have a way to help me ...
thanks a lot
Edit:
It 's difficult to explain what I am Trying to do.. The asp.net page must show a message to the user and this message must appear directly without refreshing so I was trying to use a thread which listen wait the message and then run an AJAX code to show the message ..
You can't. The browser and the codebehind (the C#) live in different worlds, and once the Page Lifecycle completes (shortly after RenderComplete), the server is done with the request.
It sends the generated HTML to the client and never looks back.
In the onunload event in javascript, you could send an AJAX request to the server to tell it that the user is leaving the page, but that would be highly unreliable, and if you depended on that exclusively to kill threads you would have a major problem on your hands.
Generally, what you're trying to accomplish would be better accomplished another way - so as others have said, let us know what you're trying to do and we'll give suggestions.
You can do this with PageMethods which works with Ajax
First you catch the onunload event on your script page :
body onunload='javascript:PageMethods.UnloadForm();'
then u enable PageMethods on the scriptManager AJAX you have to add to your page :
asp:ScriptManager ID="ScriptManager1" EnablePageMethods="true"
runat="server"
after, you create your PageMethods Code-behind method in C#:
[System.Web.Services.WebMethod]
public static void UnloadForm()
{
// your stuff
}
Hope this will help you.
My actual pb is that Onunload event is generated without closing my page cause of an AJAX timer. But if you don't add a timer, you shouldn't have this pb.
There is no request sent when the page is closing, so right out of the box, the answer is no. However, you have a few options.
One is to send an XmlHttpRequest (Ajax call) from the javascript onUnload event to a WebMethod.
Another is to execute code at the next beginning of the next pageload, which would cover cases besides those in which the user leaves your site for another or closes their browser.
Finally, there are server-side events you can use for, say, session expiration.
What is it exactly that you're trying to do? Maybe we can help come up with a better way to accomplish it.
Just curious: what kind of threaded process are you running? To your question, the only place you're going to be able to capture the event of the browser being closed is in Javascript... you could make an ajax call back to the server to kill whatever thread you've got running for the session, but as others have said, this isn't reliable.
In short there's no direct way to do what you're wanting to do. The best you could hope for is to hook the Sesion_OnEnd event.
It is a poor coding practice to start a worker thread that is dependent upon a page closing for its cleanup as you have little control over what happens on the client browser. Perhaps you could re-think the architecture of this, or at least expound on what this worker thread is actually doing so a better solution can be recommended for that.
If the work that the worker thread is set up to do has a clear path to code completion, the garbage collector will handle the cleanup and there is no cause for concern. If your using a thread from the thread pool to perform your background task via the QueueUserWorkItem construct, then the thread will make itself available for use again in the pool once the work is completed, and you have nothing to worry about as long as you ensure proper disposal of unmanaged resources if any.
As Mike pointed out in a comment, you should really set up a web service that some JavaScript on the page can poll periodically - this would then go and interagate the queue, check for messages, and if it finds one, display a message to the user.
This site has a function very similar to that when you are answering a question - it has a "Heartbeat" javascript call that polls the server looking for new answers - if it finds some, an orange message bar appears at the top of the page telling you there are new answers, and would you like to view them?