ASP.NET - How to track event from previous postback? - c#

I have a requirement to check for a certain condition on postback before redirecting (Response.Redirect) to another page.
Note... I cannot use JavaScript to detect whether or not to confirm (this is also a requirement) :s
Pseudo:
protected void lbtnRedirect_OnClick(object sender, EventArgs e)
{
if (showConfirm)
{
// Set flag for client side
this.ShowConfirm = true;
// Track this event for next postback.
}
else
{
Response.Redirect("somepage.aspx");
}
}
If the showConfrim flag == true, then the client will be show a modal dialog box asking them if they are sure they want to redirect. If the user clicks on "Yes", then the page posts back and the desired effect is that the lbtnRedirect_OnClick event is fired. How would I about tracking the lbtnRedirect event?
Edit:
I have no problem tracking the flag to show the modal (yes JS must be used to show the modal... somethings you just cannot get rid of :)). I should have been more clear.
It is when the user clicks "Yes" to continue the redirect. The page will postback again but needs to know which event to go through.
i.e. Suppose there are 3 onclick events, 1) lbtnRedirect1_Onclick 2) lbtnRedirect2_OnClick 3) lbtnRedirect3_OnClick... each of which does the confirm check.
Each onclick event does the check. So when the user clicks on "Yes" on the modal, how does the page know which event to drop back into?

You can use ViewState if you're in WebForms.
Implement a ShowConfirm property encapsulating ViewState["ShowConfirm"].
In the first postback you'll set ShowConfirm 'true', and this will activate that modal during the render (if ShowConfirm is true, that's setting as visible 'true' some control).
In the next postback, you'll set ShowConfirm 'false' because is 'true', and finally you'll do the whole redirect!

You can use an ajax call from javascript to set the required values.

Since the postback will happen before even the execution reaches to your button click event we need a workaround here, And if you don't need JS as your requirement, so take a look at
Implementing Client Callbacks Programmatically without Postbacks in ASP.NET
This is much like a wrapper for XMLHttp Ajax call IMHO.

You cannot easily create a model form, without javascipt.
One suggestion I would make is to have panels in your page.
Panel one is visible.
On submit one; panel one hides and panel two is visible asking for a confirmation.
On panel two is a confirm button, clicking this button your redirection is performed.

Related

Can a client get to a button click event programmatically if the button is not rendered? [duplicate]

This question already has answers here:
Is making an asp:Button control invisible enough to be sure users won't be able to click it?
(3 answers)
Closed 7 years ago.
This is in ASP.NET web forms, I have a save button on a screen. When I load the page initially, under certain conditions, the save button is not rendered.
button1.visible = false
In my button clicked event, I have this
public void button1_click(Object sender, EventArgs e)
{
SaveData();
}
The only security preventing the user being from being saved is on whether the save button is rendered.
In MVC, it would be trivial to access the save button action method just by making a HTTP POST to the server with my own modified request.
In ASP.NET Web forms, I'm a little bit confused because it relies on the encrypted ViewState being posted back. Do I still need to add this security to the button1_click event too? If so, then can you tell me how a client can fire a postback to the server that would reach the button click event without the button being visible?
That is one of the common mistakes about ViewState - it DOES NOT serve your click events and many other things.
Each click on button (or checkbox if autopostback is enabled) raises an form submitting to server. And all info about what was clicked is included in form postback data as plain text. Then server parses this data and, as your button has IPostBackDataHandler implemented, it raises appropriate events like "button id has been clicked". So, you can actually change request body:
D__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=%2FwEPD...&ctl00%24_pdContent%24txtEmail=qwe%40aeqw.ry&ctl00%24_pdContent%24btnRtnUser=Login&__EVENTVALIDATION=%2FwEWDAL424aUAQLjtYbqCAKu8qTUCQLXm%2BfNAwKk2O%2B4DgK3ypStCAL6q%2BaACgKBnvb9CQLr8ey6CALxoZvDCALFt96ABgLMorjMAwoW3zW69NNlOXygWNnB6luGVWnk
Above you can see content of input with id=ctl00__pdContent_txtEmail and clicked login button with id=ctl00__pdContent_btnRtnUser.
More explanation about server events in WebForms here.
And please read more about ViewState here or even better explanation here.
https://stackoverflow.com/a/24064375/279911
According to this answer on another question, it looks like it is impossible to reach the button click event if the button is not rendered as long as you have the relevant security settings set.
Yes, setting a button's Visible property to false is enough to prevent
its Click and Command events from being raised, as long as you don't
turn off the default ASP.NET security features.

Is there a way to let an asp.net page "catch up" to itself?

I'm working in C# and I need a button to become instantly disabled when a user clicks it. However, if I put as the very first line in the OnClick function
MyButton.Enabled = false;
it does nothing. The button remains enabled until it hits some sort of stop, whether it be the Catch block or the end of the function.
I was thinking that in VB/VBA you can use DoEvents() and that allows the code to catch up to itself. However, in C# there doesn't appear to be a DoEvents method.
This is a little different than the linked question, in that my OnClick code looks like:
OnClick="btnSubmit_Click"
and that user's OnClick code looks like:
onClick="this.disabled=true;
this.value='Sending…';
this.form.submit();"
When I tried to change my code to:
OnClick="this.disabled=true; btnSubmit_Click"
I got an error.
Compiler Error Message: CS1041: Identifier expected; 'this' is a
keyword
How can I do this in a C#/asp.net environment?
OnClick is a server-side event of the Button. So you cannot write:
OnClick="this.disabled=true; btnSubmit_Click"
OnClick accepts only the method-name of the server-side event handler.
If you want to handle the client-side button-click event to prevent that the user can click on it multiple times use OnCLientClick:
OnCLientClick = "this.disabled=true;"
You also have to set UseSubmitBehaviour to false.
Read: Disable a button control during postback.
You will need to utilize client-side JavaScript. One way is to utilize the OnClientClick property of your asp.net button control.
https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.button.onclientclick(v=vs.110).aspx
This is server-side and will be executed on PageLoad/Postback -
MyButton.Enabled = false;

On leaving a control, how can I give that control focus again?

I've got TextBoxes in a C# form. The user enters data, and then when they leave the control (almost always by hitting Tab), I check the data to make sure it's valid. If it is invalid, I want to highlight their text so they can immediately fix it rather than having to click it.
Right now, on Control.Leave, I validate their entry. This works just fine. However, since they hit Tab, right after they dismiss the error message, it goes on to the next object, even though I've got ((TextBox)sender).Focus();
How can I have the above line fire after the form Tabs to the next control.
You may want to look into Control.CausesValidation property
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.causesvalidation(v=vs.110).aspx
You can validate the control prior to the user leaving focus rather than waiting on Focus moving itself.
And here's MSDN documentation for Control.Validating event, does a good job at laying out the sequence of events when gaining / losing focus of a Control.
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.validating(v=vs.110).aspx
Notice how Control.Validating and Control.Validated are launched prior to Control.LostFocus. You can perform your validation step prior to allowing the user to lose focus of your Textbox.
There's also a pretty good previous answer on stackoverflow.com which outlines how to do this: C# Validating input for textbox on winforms
If you handle the Control.Validating event, setting e.Cancel to true will stop the change of focus from occurring.
Note that this method will also stop buttons from working, so you may need to set Control.CausesValidation to false on certain buttons.
You will also need the following snippet on the main form to allow the close button to work:
protected override void OnFormClosing(FormClosingEventArgs e) {
e.Cancel = false;
base.OnFormClosing(e);
}
Try using the LostFocus event on the TextBox to Focus it again

How to globally cancel post-back events for specific business logic?

I would like to be able to display a page, but with all controls disabled. The idea is for a user to view a standard page, but not actually interact with the page. Disabling all UI-controls server side is simple enough, but my main concern is an "inventive" user attempting to manually post the form back with fake information. My question is two fold:
Will built in event validation catch the devious activities?
If event validation doesn't catch it, is there a way to globally throw away the postback event (e.g. the button click, not the full life cycle)
No, you can't stop the normal Postback process.
How are you determining if the page should be disabled? Upon Postback use that same check in your button handler. If it's true, then don't save any information.
public void button1_Click(object sender, EventArgs e)
{
if(Page is disabled)
{
return
}
//Do normal save routine
}
Addressing one of your two questions:
If event validation doesn't catch it, is there a way to globally throw away the postback event (e.g. the button click, not the full life cycle)?
One option may be to add a value to the ViewState, and if that value exists on a postback, redirect the user to an error page. A user tampering with the viewstate should be caught. This doesn't meet your wish to throw away only the postback event, but maybe redirecting to an error page after receiving a postback from a page you thought no postbacks were possible from is ok.
if (ViewState["PageSetToReadOnly"] != null)
{
// Redirect to error page.
}
Another option would be to check if it is a postback in the page's PreInit event, and if so, unwire event handlers:
if (Page.IsPostBack)
{
this.Button1.Click -= new EventHandler(Button1_Click);
}
The best way I think to globally cancel the postback is to override this Page method. You can perform whatever logic you need to set the DoNotProcessPostBack during the OnLoad event :
Protected Overrides Sub RaisePostBackEvent(sourceControl As IPostBackEventHandler, eventArgument As String)
If DoNotProcessPostBack = False Then
MyBase.RaisePostBackEvent(sourceControl, eventArgument)
End If
End Sub
sourceControl is the control performing the postback and skipping over the MyBase.RaisePostBackEvent basically nullifies raising the event for it.

Loading ASP.NET user control at run time

I have an ASP.NET user control with a button, and I want to add it to the page when the user clicks a button from another user control. I have created an event handler to the first user control to handle it from the page and add the second user control to a page. Everything is working normally, but the button on the second user control doesn't respond to the event.
I place the second control on RadAjaxPanel
Note: When I add the second user control at design time its working fine.
All dynamically created controls should be added by the end of Page_Init (though sometimes you can get away with them added by the end of Page_Load).
If you're only adding them based on a button click event then you've done this in the event handers which fire AFTER Page_Init and Page_Load in the lifecycle - This is why your events don't fire and why it works fine when you add at design time.
This is because when a button is clicked on the second user control - the whole page lifecycle starts again. The page goes through Page_Load and Page_Init first and your control doesn't get loaded here. So, when the page lifecycle handles the "handle postback events" part, the control no longer actually exists, so the event doesn't fire.
Conversely, when you add at design time, the control exists in Page_Init and Page_Load so is able to handle the postback events from the user control because it already exists in the control tree - if this makes sense.
You need to think how you can restructure so they're added by the time Page_Load has finished at the very latest or it won't work. Without code samples or more detail it's hard to suggest exactly how you might do this. One possibility would be to set it visible instead of loading it outright - but if the control does some 'heavy lifting' on load like database hits or API calls then this might not be suitable for you.
I did something similar. What I did was to load some controls dynamically based on a selection from a DropDownList. If you have a method which loads the control for you, let's call it LoadControls(), then you can do something like this:
DropDownList_Click {
ViewState("LoadControls") = true;
LoadControls()
}
By setting the ViewState variable, you can then indicate Page_Load to load the controls on future postbacks:
Page_Load {
if (ViewState("LoadControls") == "true")
{
LoadControls();
}
}
This has the effect of then loading the control on-the-fly when the event first happens, and then at future times in the lifecycle.

Categories