Prevent double submiting in asp:CommandField - asp.net

Have this code:
<asp:UpdatePanel ID="id">
<asp:CommandField ButtonType="Image" InsertImageUrl="url/here" ShowInsertImage="true" ValidationGroup="valGr" />
</asp:UpdatePanel>
How to prevent double clicking on this button in C# code.

You can first create a flag that hold the submit and add it to the form. Then open and close that flag when the UpdatePanel go for update and while is waiting for the return.
For example this code is allow the submit of the form (and of the UpdatePanel) only when the
fAlloToSubmit is true:
<script>
var fAlloToSubmit = true;
function AllowFormToRun()
{
if(!fAlloToSubmit)
alert("Please wait for the page to fully re-loaded.");
return fAlloToSubmit;
}
</script>
and on code behind you set that on the form.
protected void Page_Load(object sender, EventArgs e)
{
Page.Form.Attributes["onsubmit"] = "return AllowFormToRun();";
}
And now for the UpdatePanel, you open that flag the moment you go for update, eg the moment you click that command as:
<script>
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
function InitializeRequest(sender, args) {
// here is run when you click the command on the UpdatePanel
fAlloToSubmit = false;
}
function EndRequest(sender, args) {
// here is come after the upadate of the command
fAlloToSubmit = true;
}
</script>
The trick here is that I hold the form to submit and not looking every control on page to disable it.

Related

Value returned from jQuery is always null when accessing it from codebehind in asp.net

My master page contains a menu which is dynamically created in <ul><li><li><ul/> format.
When I click on it, I want to pass its ID to codebehind for passing it into base class for its permission. But am getting value from jQuery always null in codebehind - but am getting value in jQuery function.
<script type="text/javascript">
$(document).ready(function () {
$('#nav li').click(function () {
debugger;
var vals = $(this).text();
document.getElementById('hdnForLabel').value = vals ;
});
});
</script>
This page load am using in Master Page.
protected void Page_Load(object sender, EventArgs e)
{
GetMenus();
string pageids = hdnForLabel.Value;
BasePage BasePage = new BasePage();
BasePage.LoadSettings(pageids );
}
Have you checked if the ID of your rendered hidden control is really 'hdnForLabel'? It might be something along the line of 'ctl00_hdnForLabel'.
You could use jQuery to check if the value has been set on the client side:
<script type="text/javascript">
$(document).ready(function () {
$('#nav li').click(function () {
debugger;
var vals = $(this).text();
document.getElementById('hdnForLabel').value = vals ;
alert( "Value: " + $("#hdnForLabel").val());
});
});
</script>
Please note that a value set for hdnForLabel.Value is only available when the page is sent back to the server via postback
protected void Page_Load(object sender, EventArgs e)
{
GetMenus();
if (IsPostBack) {
string pageids = hdnForLabel.Value;
BasePage BasePage = new BasePage();
BasePage.LoadSettings(pageids );
}
}

OnClick event of dynamically created LinkButtons is not working

I’ve tried several solutions for this problem but none of them worked.
Basically, I have a table of employees and the user have the choice of adding an employee dynamically thru an update panel. Each employee is being added as LinkButton and this button will fire ajaxToolkit:modalpopupextender window through OnClick event, and this window will show the employee details.
The problem is when I click on the employee name the popup window will show up BUT the details wont.
Here is the code in which I’m creating the buttons and putting it in the table:
LinkButton lbtn = new LinkButton();
lbtn.ID = employee_arry[i] + "_lbtn" + i;
lbtn.Text = employee_arry[i];
lbtn.Click += new EventHandler(this.employee_info);
lbtn.CausesValidation = false;
lbtn.Attributes.Add("runat", "server");
cell.Controls.Add(lbtn);
and here is the employee_info method:
//the info will be pulled from the database…
public void employee_info(object sender, EventArgs e)
{
name.Text = "employee name";
dept.Text = "employee department";
jobt.Text = "employee job title";
email.Text = "employee email";
tel.Text = "employee telephone";
ModalPopupExtender1.Show();
}
Check this answer
https://stackoverflow.com/a/11127064/1268570
This explains the behavior of dynamic controls
You need to consider:
Dynamic controls should be created in the PreInit event when you are not working with a master page, if you are, then create the controls in the Init event
Avoid setting properties that can be changed in each post in these events because when the view state is applied (in a post event) the properties will be overridden
Dynamic controls must be created every time the page is posted, avoid this if(!this.IsPostBack) this.CreatemyDynamicControls();
When you create the controls in the PreInit or Init events, their states will be automatically set in a post event, which means in the LoadComplete event your controls will contain their state back even when you create them again in each post and even when you did not explicitly set their state. Note this behavior is different when you are dealing with controls created at design time, in that case, the event where the state has been set is the Load event
Event subscription should occur before the PageLoadComplete or they will not be raised
Edit 1
In case you have not found a solution, this is a way to do it (full working example):
ASPX
<asp:ScriptManager runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server" ViewStateMode="Enabled">
<ContentTemplate>
<asp:Panel runat="server" ID="myPanel">
</asp:Panel><br />
<asp:Button ID="Button1" Text="add control" runat="server" OnClick="addControl_Click" /><br />
<asp:Label ID="lblMessage" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
Code Behind
protected int NumberOfControls
{
get
{
if (ViewState["c"] == null)
{
return 0;
}
return int.Parse(ViewState["c"].ToString());
}
set
{
ViewState["c"] = value;
}
}
protected void addControl_Click(object sender, EventArgs e)
{
this.NumberOfControls++;
this.myPanel.Controls.Add(new Literal { Text = "<br />" });
this.myPanel.Controls.Add(this.CreateLinkButton(this.NumberOfControls));
}
protected void Page_PreLoad(object sender, EventArgs e)
{
this.CreateDynamicLinkButtons();
}
private void CreateDynamicLinkButtons()
{
for (int i = 0; i < this.NumberOfControls; i++)
{
this.myPanel.Controls.Add(new Literal { Text = "<br />" });
this.myPanel.Controls.Add(this.CreateLinkButton(i + 1));
}
}
private LinkButton CreateLinkButton(int index)
{
var l = new LinkButton { Text = "MyLink" + index.ToString(), ID = "myLinkID" + index.ToString() };
l.Click += (x, y) =>
{
this.lblMessage.Text += "<br/>ID: " + (x as LinkButton).ID;
};
return l;
}
Output

Handling events from dynamic controls NOT added on Page_Load?

I've read a few articles on here and the web that have informed me that I cannot simply add a new control dynamically to the page, wire it to a handler, and expect it to work.
The solution given each time is that the dynamic controls need to be added to the page on Init each time.
My problem is, my controls are NOT added to the page on init, they are added after ANOTHER postback.
the workflow is this:
Page Loads
User fills in a textbox, clicks a button
Page Posts back, creating dynamic link controls in the button_click event based on the input
User clicks one of those link controls to proceed to the next step.
so if this is the behavior I need to support, is there any way to do this? It has to happen in the button_click of step 2, because the dynamic controls are based on the input the user puts in step 2.
have I painted myself into a corner here? how else could I handle such a workflow?
After you dynamically create a link button, set a flag in your page's view state. On postback, re-create the link button if the flag is set in view state. Here's a demo:
Markup:
<asp:Button runat="server" ID="button1" OnClick="button_Click" Text="Create button A" CommandArgument="A" />
<asp:Button runat="server" ID="button2" OnClick="button_Click" Text="Create button B" CommandArgument="B" />
<asp:PlaceHolder runat="server" ID="placeHolder"></asp:PlaceHolder>
Code-behind:
public partial class Default : System.Web.UI.Page
{
private bool LinkButtonCreated
{
get { return ((bool?)this.ViewState["LinkButtonCreated"]).GetValueOrDefault(); }
set { this.ViewState["LinkButtonCreated"] = value; }
}
private string LinkButtonCommandArgument
{
get { return (string)this.ViewState["LinkButtonCommandArgument"]; }
set { this.ViewState["LinkButtonCommandArgument"] = value; }
}
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
if (this.LinkButtonCreated)
this.CreateLinkButton(this.LinkButtonCommandArgument);
}
protected void button_Click(object sender, EventArgs e)
{
if (!this.LinkButtonCreated)
{
string commandArgument = ((Button)sender).CommandArgument;
this.LinkButtonCreated = true;
this.LinkButtonCommandArgument = commandArgument;
this.CreateLinkButton(commandArgument);
}
}
private void CreateLinkButton(string commandArgument)
{
LinkButton linkButton =
new LinkButton
{
ID = "linkButton",
Text = "Click me",
CommandArgument = commandArgument,
};
linkButton.Click += this.linkButton_Click;
this.placeHolder.Controls.Add(linkButton);
}
private void linkButton_Click(object sender, EventArgs e)
{
LinkButton linkButton = (LinkButton)sender;
linkButton.Text = "I was clicked! Argument: " + linkButton.CommandArgument;
}
}

Random image in UpdateProgress

I have a wizard control inside an updatepanel. Some of the wizard steps take a few seconds to display, so I want to show an updateprogress control while they're loading. This is working, but I'd like to show a different image (random image selected from a folder) in the progresstemplate between each wizardstep.
I am able to access the image control and change the ImageUrl, but the progresstemplate never updates. It retains the first random image chosen from the very first time it loads.
I've tried updating the imageUrl on PageLoad and also by overriding the Render() method, but neither works.
<asp:UpdateProgress ID="UpdateProgress1" runat="server" DisplayAfter="500" >
<ProgressTemplate>
<div class="modalWrapper">
<div class="updateProgress">
<asp:Image ID="imgLoading" runat="server" AlternateText="Loading..." />
</div>
</div>
</ProgressTemplate>
</asp:UpdateProgress>
In codebehind:
protected void Page_Load(object sender, EventArgs e)
{
System.Web.UI.WebControls.Image img = (System.Web.UI.WebControls.Image)UpdateProgress1.FindControl("imgLoading");
if (img != null)
img.ImageUrl = PickImageFromDirectory("~/images/loaders/"); //returns "~/images/loaders/randomimage.gif"
}
ALSO TRIED:
protected override void Render(HtmlTextWriter writer)
{
System.Web.UI.WebControls.Image img = (System.Web.UI.WebControls.Image)UpdateProgress1.FindControl("imgLoading");
if (img != null)
img.ImageUrl = PickImageFromDirectory("~/images/loaders/"); //returns "~/images/loaders/randomimage.gif"
base.Render(writer);
}
Your image is more than likely not being reloaded because the UpdateProgress sits outside your UpdatePanel. The nature of the UpdatePanel is that only the controls within it are updated on an asynchronous request. =)
Here's what you can do:
Change PickImageFromDirectory to be a static method and mark it as a WebMethod in the code-behind:
[WebMethod]
public static string PickRandomImage()
{
// Logic to return the full path to a random image
}
Then, on the client-side place the following script at the bottom:
<script type="text/javascript">
function requestEnded()
{
PageMethods.PickRandomImage(imageSuccess, imageFailed);
}
function imageSuccess(result,ctx,methodName)
{
document.getElementById('<%= imgLoading.ClientID %>').src = result;
}
function imageFailed(err,ctx,methodName)
{
alert(err);
}
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(requestEnded);
</script>
After every asynchronous postback this will call your server-side web method and set the image src to a random url. =)
You can specify an url than goes to an aspx page :
<asp:Image runat="server" ImageUrl="GenerateImage.aspx"/>
In GenerateImage.aspx :
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Response.ContentType = "image/jpeg";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Write(GetRandomImageData());
Response.End();
}

Validation Before Postback Event on Masterpage Asp.net

I was wondering if anyone knew of a way to do some client side validation with jquery and then run the postback event manually for a asp.net control?
Here's a sample Master page
i.e.
<script type="text/javascript">
$(document).ready(function() {
$("#<%=lnkbtnSave.ClientID %>").click(function() {
alert("hello");
// Do some validation
// If validation Passes then post back to lnkbtnSave_Click Server side Event
});
});
</script>
<asp:LinkButton ID="lnkbtnSave" runat="server" onclick="lnkbtnSave_Click" ><asp:Image ID="Image3" runat="server" ImageUrl="~/images/save.gif" AlternateText="Save" />Save</asp:LinkButton>
Master Page Code Behind
public delegate void MasterPageMenuClickHandler(object sender, System.EventArgs e);
public event MasterPageMenuClickHandler MenuButton;
protected void lnkbtnSave_Click(object sender, EventArgs e)
{
// Assign value to public property
_currentButton = "Save";
// Fire event to existing delegates
OnMenuButton(e);
}
protected virtual void OnMenuButton(EventArgs e)
{
if (MenuButton != null)
{
//Invokes the delegates.
MenuButton(this, e);
}
}
Content Page Code behind
protected void Page_Load(object sender, EventArgs e)
{
Master.MenuButton += new Form.MasterPageMenuClickHandler(Master_MenuButton);
}
void Master_MenuButton(object sender, EventArgs e)
{
switch (Master.CurrentButton)
{
case "Save":
Save();
break;
case "New":
Response.Redirect("ContentPage.aspx");
break;
default:
break;
}
}
Also the control lnkbtnSave is in a master page so how would i determine which content page i'm on since each content page will have it's own controls to validate.
Thanks for any help
If you look at it in reverse it could be simplified. Instead of doing validation and then initiating the postback, you could validate and prevent the postback if needed.
$('#<%= lnkbtnSave.ClientID %>').click(function(e) {
if (!validate()) {
e.preventDefault(); //will stop the page from posting back.
}
});
If you really need to initiate the postback (and do it the other way) you could explicitly call the __doPostBack() function that ASP.NET puts on the page for you after doing your validation.
// This does the exact same thing as above, but it explicitly calls __doPostBack
// If you use the above code __doPostBack will be called automatically for you.
$('#<%= lnkbtnSave.ClientID %>').click(function(e) {
if (validate()) {
__doPostBack('<%= lnkbtnSave.ClientID %>','');
}
e.preventDefault();
});
Let me know if any of this needs clarification.
For the first question you should be able to just return true to cause the linkbutton to postback and return false to stop it.
$(document).ready(function() {
$("#<%=lnkbtnSave.ClientID %>").click(function() {
alert("hello");
var isValid = false;
// Do some validation
return isValid;
});
});
For your second question, you could have each page add their own version of the validation script, and have the function in the masterpage use it to determine validity:
Master Page:
$(document).ready(function() {
$("#<%=lnkbtnSave.ClientID %>").click(function() {
return pageIsValid();
});
});
Content Page:
function pageIsValid() {
var isValid = false;
//validation logic
return isValid;
}
You can just use a CustomValidator control and set it's ClientValidationFunction property.

Resources