Should I just let the user hang? - asp.net-mvc

I am not really sure what to do in this situation. I have some jquery ui 1.7 tabs that are ajax enabled. Now when a tab is clicked it goes to my asp.net mvc controller action method. That then does whatever is needed and return a partial view.
Now I don't know why but sometimes my server hangs but then again I am guessing all servers hang since sometimes when I go to sites it take forever to load but if you do a refresh it loads up instantly and that's the same case with my site.
My site will load up a tab super fast for X number of times then all of a sudden a request will just hang and maybe like 15seconds later it will load up. Or if you just refresh the page it will go back and start loading them up super fast again.
The problem though is the request is sent to the server where it hangs. So I tried to setup a jquery timeout on all my ajax stuff and that calls an abort to the jquery ui tabs.
But it never works and I guess from what I gathered reading on this site is because the request is on the server and abort won't stop stuff on the server. So if I look at firebug that request that hanged is stil running.
Now this causes a huge problem for me since it screws up the entire page what is heavily ajax. Like if the user tries to click on say another tab they will most likely have to click 2 times to get it to load up. Another thing what happens is if that request ever finish hanging whatever tab they are on will merge with that tab. So sometimes one tab will have parts from all the other tabs.
So if it hangs and does not finish it really messes with the ajax tabs. I have no clue how to fix this.
So I am not sure what to do.
Let them hang for however long it takes the server to figure out how to finish that request(when a ajax request is made I disable all tabs. This is because if a person say loaded up a tab and did not let it finish and tried to go to another tab the same problem would occur with the tabs merging together). Or abort the request and have a screwed up tabs.
Great choices I got. Anyone got any better choices?
Thanks

We have a similar situation here in that the 1st person to hit the site for the day will incure a 15 second delay while things are loaded.
In our situation, on all calls to the server via jQuery, I have set a normal javascript timeout for 2 seconds. After 2 seconds I pop up a small div saying something like things are talking longer than expected and please be patient.
after a further 6 seconds i close that div and open a new one with more of an apology.
not a great solution but it does keep the user in the loop, comfortable that things are ticking along and that we acknowledge things are not perfect.
warm and fuzzies as we call them here. :)

I'm not sure what you mean by "jquery timeout". if you mean setTimeout, that definately won't work. If you mean, on the other hand,
$.ajax({
url:"myserverprocess",
timeout: 200,
error: function () { /* try again */ },
success: function (myadata) { alert("mydata")}
});
then that should work. Try the timeout option if you haven't yet.
edit:
you could try :
$(selector).tabs({
ajaxOptions: {
url:"myserverprocess",
timeout: 200,
error: function () { /* try again */ },
success: function (myadata) { alert("mydata")}
}
});

We've had good success using jquery queue manager - http://www.protofunc.com/scripts/jquery/ajaxManager/
When a second request is performed it aborts the first request. I'm not sure about a timeout, but there are several options you can play with.

You could use Jquery to set a timeout on your ajax call and then catch it in the error section. Once caught, you could deal with retrying or doing any needed cleanup.

Related

Playwright retry on actions

I have a scenario here:
Click element A (a button), trigger element B (say, a div) to appear. However due to multiple factors, clicking might fail to trigger the event. The reason could be clicking too soon when he page is actually fully settled. So I need to redo the click a couple of times. There not seem to be a mechanism with in Playwright to do step level retry when condition is not met.
It sounds like a common requirement in test automation though. I am wondering how do you tackle this problem.
Some suggestion or custom code to retry failed steps?
I think what you're looking for is .toPass
await expect(async () => {
await page.locator('button').click();
await expect(page.locator('div')).toBeVisible();
}).toPass();
It'll retry the code you'll give it and wait for it to pass.

Playwright: how to wait until there is no animation on the page?

I'm trying to figure out how to check whether the page has fully loaded in Playwright. await page.waitForLoadState('networkidle'); doesn't always work for me on Javascript-heavy sites. I've resorted to taking a screenshot base64, waiting 100 ms, taking a new screenshot, and comparing whether those are the same. However this doesn't seem ideal, is there any way to ask Playwright when the last animation frame was redrawn?
There are several options that may help you.
1. Solution 1:
First, you can maybe determine which element is loading last, and then go with
page.waitForSelector('yourselector')
or even wait for multiple selectors to appear
page.waitForSelector('yourselector1','yourselector2')
2. Solution 2
page.waitForLoadState('domcontentloaded')
Because
page.waitForLoadState('networkidle')
by default will wait for network event and if 0.5 seconds nothing is network trafficking it will say, I am no longer need to wait. And that is why you maybe have stohastic beh.
If the given solution doesn't work for you, you can try with locator.
page.locator(selector[, options])
It has multiple api like locator.isDisabled or locator.waitFor([options]) or locator.isVisible([options]) or locator.frameLocator(selector) ....... a lot more.
see the below link here:
https://playwright.dev/docs/api/class-locator

Grails view hangs when calling a controller action

I have a view that has a link using the g:link GSP tag with action that runs and updates on a significant number of rows, so it takes some time. In the meantime, the browser is in limbo and times out after 30 sec (which is the timeout on the servlet container).
Problem:
It is a bad user experience that the page times out.
The browser submits the controller action each time the timeout occurs. I have handled this by checking if the query is already running so this is no longer an issue.
Question:
How can I trigger the controller action and reload the page to the same view? Or is there a better way to handle this like triggering the action async?
I tried to reload the page using js, but it does not seem to reload the page. I have read about implementing a message queue, but it seems like a lot of work for a simple issue. Any ideas will be good. Thank you in advance.
View:
<li>
<a class=""
href="${g.createLink(controller: "hello", action: "dbAction")}">Run Update on DB
</a>
</li>
Controller Action:
def dbAction() {
some code...
myservice.dbAction();
redirect(action: 'index')progress"
}
}
My Service dbAction:
def dbAction() {
Sql sql = getSql()
sql.executeUpdate('''
update mytable
set
mydata = calculate_data,
updated_by = 'dbAction',
updated_at = now()
where
id in (1,2,3)
}
I have exactly your problem. The query takes so long to run, the controller cannot respond back to the browser. So, the browser times out.
I tried 3 different ways to fix this.
The easy way out:
I am using Tomcat. So, I set the connection timeout value longer. The connectionTimeout variable is in the server.xml file.
The lazy way out:
I don't know if Grails has any sort of Message Queue function or not. So, I rolled my own. When I click the submit button to run a very long update query, the action will INSERT INTO a sort of update command in a database table along with the state. I then use Quartz to schedule maybe every 10 seconds to read this table to check the state. If the state is NEW, I change the state to "IN PROGRESS". And then I let the trigger to run the update query in the background. After it finish, I change the state to FINISH.
So, the action is just adding a row to the database and then respond back the view that says something like... You have issued the request. The system will process your request in a few moment.
The hard way out:
I went over all my SQL and functions in the actions to calculate the time it will take the SQL and codes to finish the query. I then rearrange/rewrite the functions and procedures. I am not good enough for this. If I can get to O(n), that will be enough for me.

The timeout period elapsed prior to completion of the operation or the server is not responding

I Created A VIEW IN MY ASP.NET MVC APPLICATION.
View class retrieves a data of 6100 rows
that class is used in one of my view which fills grid with data it can also be sorted.
it will load nicely for first time then sorting also works fine but when i click on last page link it takes time and finally gives following error
The timeout period elapsed prior to completion of the operation or the server is not responding
anyone can help me please i am not getting WATS the problem
Sounds like the request time is reaching the max allowed (default in ASP.NET = 30 secs). I don't think its as the back button as much as the request is randomly taking 29 secs, 31 secs, etc.
You may want to try a pagination approach to displaying your data instead of loading 6,100 rows at once - this will reduce the load times.
Check out this link for a pagination example.
Another idea would to use page caching. But I would recommend pagination.

How can I prevent the user from navigating back to a previous page?

I have an ASP.NET MVC application, with three views: view1, view2, view3. The logic way for the user to navigate through these is: view1 -> view2 -> view3.
When the user reaches view3, then I must prevent them from loading view2, even by using the "Back" button in their browser.
What is a good, browser-independent means of implementing this?
In most of the applications you have to cope with the back ability from the browser. The user is used to it and he wants to use it and he more or less will hate pages that try to trick them when going back and forward.
Don't try to fool you user think about what he wanted to do and then try do deliver a not completely broken page.
Add a check of referrer page on page load in your application and then show a page or redirect user back to used view. You cannot manipulate or disallow basic navigation on client, but you can solve this problem server-side
I can't comment on the earlier posts, but note that some browsers don't pass referrers, and thus the earlier solution would break (throw an exception, actually).
There are two steps to this:
1) You have to prevent browser-side caching. If you've got a three step process that the user walks through and it's dynamic, you're probably already doing this. If you don't prevent caching, the back button will show the cache of view1. Since step 2 is done server-side, the server won't have a chance to do anything.
2) You need to, as previous poster's have said, do something on the serverside to prevent the display. There are two ways to do this (despite my really bad pseudo code).
a) The quick & dirty way is based on the referer. For example, you'd put the following check on the controller for view2:
if (request.urlreferrer.absolutepath == "controllerview1")
{ //good }
else
{ //bad }
Also, in the case of "bad", you'll have to consider what to do. If you're using forms to pass values back and forth, you've suddenly lost when the user goes back to view2.
Note, though, that some browsers don't ever pass referrers and the above check won't do any good (and request.urlrefferer will be null). (I believe this is generally due to firewalls.) In which case you'd have to do:
b) I've done something like this before. The controller view1/2/3 is essentially a wizard where they're walking through the system. Each controller updates the db row associated with the wizard. So, view 2 would do something like:
if (dbrow.last_saved_page_num == 1)
{ // good }
else
{ // bad
redirect("view" + dbrow.last_saved_page_num + 1);
}
That is outside of the scope of javascript, and cannot be disabled (though you can tell the browser to go forward or back, you cannot prevent it). You would need a server side solution to disallow access to the pages.
There is no JavaScript solution, it would have to be implemented server side.
You can add a function to view1 and view 2 that fires on page load, if you use jquery something like :
$(document).ready(function(){ window.history.forward(); });
or you could just just do this
<html onload="window.history.forward()">
Either way will do pretty much what you want, but maybe not be the best solution in terms of user experience - but if its all you have to work with then it might be the best solution.

Resources