What is the event sequence of a a4j:commandLink or a4j:commandButton?
Is it right: onclick->actionListner->oncomplete->reRender?
Is reRender comes before oncomplete?
When action happens?
The onclick JavaScript is called the first when the enduser clicks the generated HTML element. When the JavaScript code does not return false, then all associated ActionListener implementations in the JSF side will be invoked, in the order of their association with the component. If the listeners haven't thrown any exception, then the real action will be invoked. When the action returns a successful response, then the components specified in reRender will be updated in the client side. Finally the oncomplete JavaScript will be called.
It's pretty easy to track yourself if you have a debugger in both the client and server side and know how to use it. I strongly recommend Firebug for the client side and Eclipse for the server side. You can of course also always do poor man's debugging using alert()s or System.out.println()s.
Related
I'm working on an asp.net web application and am running into this error after manipulating some controls client-side (html buttons nested in update panels):
"Invalid postback or callback argument. Event validation is enabled using in configuration or <%# Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation."
The stack trace given is:
"[ArgumentException: Invalid postback or callback argument. Event validation is enabled using in configuration or <%# Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.]
System.Web.UI.ClientScriptManager.ValidateEvent(String uniqueId, String argument) +9832822
System.Web.UI.Control.ValidateEvent(String uniqueID, String eventArgument) +114
System.Web.UI.WebControls.DropDownList.LoadPostData(String postDataKey, NameValueCollection postCollection) +65
System.Web.UI.WebControls.DropDownList.System.Web.UI.IPostBackDataHandler.LoadPostData(String postDataKey, NameValueCollection postCollection) +18
System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean fBeforeLoad) +471
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1897"
This stack trace is useless in that it's not telling me what control is causing the issue. I think I understand the basics of what the error is trying to say, but without a direction to go it's a total crapshoot as to where to start looking, particularly since I'm not manipulating any dropdown lists.
Before I go through the hassle of posting code, how can I get the complete stack trace (showing file and line number) for the error to figure out what is happening? I've been working on this problem for a week now and I'm pretty well fed up with it. Thanks.
hum, does this occur on a button click? Try moving any control validators to the top of the page, see if that helps. I guess a few more details as to "when" the error occurs. (does it occur on first page load, or due to some button click? And do you have any say JavaScript bits and parts that might have posted the page back before it is 100% rendered? I mean, something added to the page must have "started" this issue to occur. but, we quite much guessing. You could as a test in web config turn off page validation, and at least see if that works, and then try to fix and then re-enable.
Also, are you loading up data into some controls on page load?
Try then placing that "setup" and "data loading" inside of the !IsPostback (which all pages quite much need and have, right??).
So, in page load event, place that data load, and setup code you have inside of the !IsPostBack block like this:
if (!IsPostBack)
{
page load + setup + data loading code goes here
}
So, adopt the above if you have code to load up say a gridview, or even a dropdown box. I seen the above "simple" change in code fix your error, and a good number of times.
I'm running a NodeJS server which is sending notifications to the clients when somebody does something, for example, when a client deletes a row from a grid, Socket.io informs the rest of the clients that a row got deleted.
In that example, I could add something like actionType: rowdeleted to the socket.io message and then just detect the actionType on the client side and refresh the grid. Anyways, the problem is that there can be infinite number of actions (and new ones can be added), so I can't code a function for each action type on the client side.
Then I thought maybe I can send some code via socket.io and make the client run it, but I'm not sure if that is the best way for doing what I want. Also, how are the clients going to run that code? Via eval?
I'm open to any suggestion :)
Have you considered something similar, but not as eval. You clearly must have the code to execute somewhere, be it on the server side. Why not create a way to let the client know what script/code/action to get and execute it.
I have used something similar out of a similar need. The action type referenced a script in a specific path on my server (/js/actions/ACTION.js). Upon getting the command to run the action, the client would check if it has the action, if not, it would go get the action. After that it would run the action on the script. RequireJS is good for this kind of thing. It will keep track of what actions you have and what actions you don't have. It will also make sure to get the action if it doesn't have it before it run some function that needs it.
eval is evil (c)
so I can't code a function for each action type on the client side.
there's no point emiting events from server if they wont be handled on the client(s)
have a client handle funcion for each type of event your server is emiting.
Otherwise bind on all events and handle then
Is it possible to directly bind server side events to client side objects in meteor?
I would like to update a view for example when a server side event triggers. On the other hand I'd like to fire a server side method when a user clicks a view item.
I could use Meteor#methods for all the events but that seems odd.
Or can I specify an eventhandler for example using EventEmitter outside the client- and server-scope so that it is available on both sides and trigger/bind events ob that very object?
Some confused about that I am thankful for hints into the right direction.
Regards
Felix
Update:
Using Meteor#methods works great in case user events should be mapped to server side actions. The other way around is still unclear. Asynchronous actions on serverside could persist their results in a collection which is pub/sub'ed to the client, which in turn could update some view due to the reactive context. But thats odd, cause persisting that kind of info is slow, wasted space and time. Any suggestions?
I believe you can use the Collection.observe on the server side to 'observe' events on the Collection as clients are inserting, updating, removing, etc... That might be a start if you are focused on Collections alone. I used it like a sort of server side event loop to watch for collection changes.
When a user clicks on something in a view try binding a Template Event to the View css selector and then calling a Meteor method which will notify the server of the event. See the examples of binding a key handler and/or button handlers to a Template.entry.event which then call a Meteor method notifying the server that something happened.
What about storing the progress in Session? You could do something like this:
Template.progress.value = function() {
return Session.get('progress');
}
Then, whenever you update the Session on the server, the client template will automatically get those changes.
Out of curiosity, how exactly are you performing asynchronous actions on the server? I'm still trying to figure that out.
I need to execute an action of a controller when a user leave a page (close, refresh, go to link, etc.). The action code is like:
public ActionResult WindowUnload(int token)
{
MyObjects[token].Dispose();
return Content("Disposed");
}
On window download I do Ajax request to the action:
$(window).unload(function ()
{
$.ajax({
type: "POST",
url: "#Url.Action("WindowUnload")",
data: {token: "#ViewData["Token"]"},
cache: false,
async: true
});
//alert("Disposing.");
})
The above ajax request does not come to my controller, i.e., the action is not executed.
To make the code above to work I have to uncomment the alert line, but I don't want to fire alert on a user.
If I change async option to false (alert is commented), then it sometimes works. For example, if I refresh the page several times too fast then the action will not be executed for every unload.
Any suggestions how to execute the action on every unload without alert?
Note, I don't need to return anything from action to the page.
Updated: answers summary
It is not possible reliably to do request on unload, since it is not proper or expected behavior on unload. So it is better to redesign the application and avoid doing HTTP request on window unload.
If it is not avoidable, then there are common solutions (described in the question):
Call ajax synchronously, i.e., async: false.
Pros: works in most cases.
Pros: silent
Cons: does not work in some cases, e.g, when a user refreshes the windows several times too fast (observed in Firefox)
Use alert on success or after ajax call
Pros: seems to work in all cases.
Cons: is not silent and fires pop up alert.
According to unload documentation, with async: false it should work as expected. However, this will always be a bit shaky - for example, user can leave your page by killing/crashing the browser and you will not receive any callback. Also, browser implementations vary. I fear you won't get any failproof even.
HTTP is stateless and you can never get a reliable way to detect that the user has left your page.
Suggested events:
Session timeout (if you are using sessions)
The application is going down
A timer (need to be combined with the previous suggestion)
Remove the previous token when a new page is visited.
Why does this need to happen at all?
From the code snippet you posted you are attempting to use this to dispose of objects server side? You are supposed to call Dispose to free up any un-managed resources your objects are using (such as Database connections).
This should be done during the processing of each request. There shouldn't be any un-managed resources awaiting a dispose when the client closes the browser window.
If this is the way you are attempting this in the manner noted above the code needs to be reworked.
Have you tried onbeforeunload()?
$(window).bind('beforeunload', function()
{
alert('unloading!');
}
);
or
window.onbeforeunload = function() {
alert('unloading!');
}
From the comment you made to #Frazzell's answer it sounds like you are trying to manage concurrency. So on the chance that this is the case here are two common method for managing it.
Optimistic concurrency
Optimistic concurrency adds a timestamp to the table. When the client edits the record the timestamp is included in the form. When they post their update the timestamp is also sent and the value is checked to make sure it is the most recent in the table. If it is, the update succeeds. If it is not then someone else got in sooner with an update so it is discarded. How you handle this is then up to you.
Pessimistic concurrency
If you often experience concurrency clashes then pessimistic concurrency may be better. Here when the client edits the record a flag is set on that row to lock it. This will remain until the client completes the edit and no other user can edit that row. This method avoids users loosing changes but add an administration over head to the application. Now you need a way to release unwanted locks. You also have to inform the user through the UI that a row is locked for edit.
In my experience it is best to start with optimistic concurrency. If I have lots of people reporting problems I will try to find out why people are having these conflicts. It maybe that I have to break down some entities in to smaller types as they have become responsible for doing too many jobs.
This wont work and even if you are able to somehow make it work it will give you lots of headaches later on, because this is not how the browser/HTTP is supposed to be used. When the page is unloading (in browser) the browser will call the unload event and then unload the page (you cannot make it wait, not even my making sync ajax calls) and in case the call was going on and the browser after executing the code unload the page, the call will also get cancelled and thats why you see the call on server sometimes and sometimes it doesn't work. If you could tell use why you want to do this we could suggest you a better approach.
You can't. The only thing you can do is prompt the user to stay and hope for the best. There are a whole host of security concerns here.
I have a situation where I want to use several server side controls, which have clients side state. I want to check the state when events occur (like various clicks), and when the state is where i want it, I want to postback to the server and do some processing.
In particular, I need to make sure that at least 3 different controls have selections before I want to do a postback. Since there is no specific control that will initiate the postback, I just want to capture the selection events on the client side, then call __doPostBack() (or something similar) to initiate the processing. So i have disabled all server side events, turned off autopostback, and have wired up some javascript to handle this.
I've got all the client side code written and working, however I cannot seem to get the server-side to recognize the postback. I'm overriding RaisePostBackEvent, and checking the eventArgument for my custom argument. This doesn't work, as RaisePostBackEvent is never called.
This method has worked when I had autopostback enabled (for example, the Telerik Radgrid OnSelectChanged server side event).
Any suggestions on the best way to handle this?
Update:
When asked for sample code, it's exactly as I say above. Not rocket science.
Javascript:
function CheckState(source, eventArgs) {
// logic to test state of controls
__doPostBack("", "DoMyWork:");
}
Then in code behind I have:
protected override void RaisePostBackEvent(IPostBackEventHandler source, string eventArgument)
{
if (eventArgument.IndexOf("DoMyWork") != -1)
{
// do my server side work.
}
}
RESOLUTION:
Because this is somewhat confusing.. I'll just say what my solution was.
I used one of the controls involved in the postback and used it's UniqueID for the control parameter, then my method as the event.
if you call the __doPostBack() without parameters, asp.net cannot figure out which control fired the event and thus it cannot determine which event to fire.
you need to add the name of the control as a parameter to __doPostBack() and an argument which could be null if you dont need one
__doPostBack('textbox1','') //no arguments
__doPostBack('textbox1','12')
you can read the argument you passed in from code behind like this:
Dim arg As String = Request("__EVENTARGUMENT")