TextBox loses value after post back with TextMode Number - asp.net

Got weird problem. I have simple page with TextBox:
<asp:ScriptManager runat="server" />
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:TextBox ID="amountTextBox" runat="server" TextMode="Number" />
<asp:Button runat="server" Text="Confirm" OnClick="confirmButton_Click" />
</ContentTemplate>
</asp:UpdatePanel>
After Button click I try to get TextBox value:
public partial class test : Page {
protected void confirmButton_Click(object sender, EventArgs e) {
var answer = amountTextBox.Text;
}
}
but it's empty. If I remove UpdatePanel, I manage to get the value. If I leave UpdatePanel and remove TextMode property, I manage to get the value. But why can't I have TextBoxt with TextMode set to Number in UpdatePanel?

It is a known issue, a fix is available in .NET 4.5 RTM.
Description
HTML5 has new types for the input tag, such as type="number", which is
needed to make mobile phones display a numerical keyboard instead of a
text keyboard. When doing a full postback of the page it works in all
browsers. But if I puts these in an updatepanel on a website to do a
partical postback, then none of the new HTML input types are included
in the postback response to the server from those browsers that
understands these new types (Safari/WebKit and Opera). It works
correctly in IE8 and Firefox 4, but probably only because they have
not implemented these new types and falls back to understanding it as
a type="text" field.
Here is another question with this issue and workarounds: UpdatePanel with input type other than text in html5.

Related

Load specific part in webpage?

See below image first.
we have one sidebar navigation(ajax accordion control asp.net)
now when ever user click on link inside side bar related page(content) should display in Content goes here region.
As per given instruction entire page should not be refreshed or in other word in Back Button should not work(In Internet Explorer).
what should be the way to achieve this functionality?
what should be the best suggestion for that?
EDIT: navigation tree is inside MasterPage and Content goes region is in side content page of master page
please suggest me.....
thank you so much....
The Easiest way is to Wrap your side navigation & the Content placeholder in an UpdatePanel. Set the TreeView in the side bar as the UpdateTrigger for the update Panel. But, this approach is a little inefficient.
A slightly better way is ti just wrap the Content Placeholder in an Update Panel, along with a HiddenField in it. Upon a selection in the sidebar, update the HiddenField Value with JavaScript and then refresh the update Panel.
According to:
As per given instruction entire page should not be refreshed or in other word in Back Button should not work(In Internet Explorer).
And
sidebar tree view is in master page and Content goes here region is content page
If my understanding is correct, I think you do not need to place your TreeView control in your master page because you only want one page loading dynamically the content based on the selection of your tree view. So...Why is this important? Well if you place your tree view in your page you can use an UpdatePanel to avoid full posts.
Output of the following code
The following code covers the next points:
A TreeView control is embedded in a UserControl and placed in an ASPX page (left side)
The menu contorl exposes an event that is raised whenever the selected node changes, this event is handled in the ASPX page to dynamically load user controls depending on the user selection on the right side of the page, only one content is loaded at a time.
The controls are embedded in an UpdatePanel therefore you won't change your page and your back button in your browser won't be affected
Note: the user controls keep their state across post backs
(I'm not sure if this is the best way to do it, perhaps you could try to find a solution using only ajax, and avoid the use of the evil updata panels, but certainly this is a way to do it)
I'll try to simplify the code to reduce the size of the post, I will just post the code of one user control, the other one is exactly the same I just changed its title to difference them on the page
ASCX Menu
<asp:TreeView ID="TreeView1" runat="server" onselectednodechanged="Unnamed2_SelectedNodeChanged">
<Nodes>
<asp:TreeNode Text="link1" />
<asp:TreeNode Text="link2" />
</Nodes>
<SelectedNodeStyle Font-Bold="True" Font-Italic="True" />
</asp:TreeView>
ASCX Menu code behind
public event Action<string> MenuChanged = delegate { };
protected void Unnamed2_SelectedNodeChanged(object sender, EventArgs e)
{
this.MenuChanged(this.TreeView1.SelectedNode.Text);
}
ASPX
<asp:ScriptManager runat="server" ID="sm" />
<asp:UpdatePanel runat="server" ChildrenAsTriggers="true">
<ContentTemplate>
<asp:HiddenField runat="server" ID="currentControl" />
<table border="0" cellpadding="0" cellspacing="0" width="90%" align="center">
<tr>
<td style="width:50%; background-color: Silver">
<menu:TreeViewMenu runat="server" ID="myTreeViewMenu" OnMenuChanged="myTreeViewMenu_MenuChanged" />
</td>
<td style="width:50%; background-color: Aqua">
<p>Result:</p>
<asp:Panel runat="server" ID="myPanel">
</asp:Panel>
<asp:Label ID="lblMessage" runat="server" />
</td>
</tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>
ASPX code behind
protected void Page_Init(object sender, EventArgs e)
{
if (this.IsPostBack)
{
var cc = this.Request.Form["currentControl"];
if (!string.IsNullOrWhiteSpace(cc))
{
var uc = this.LoadControl(this.Server.HtmlDecode(cc));
this.myPanel.Controls.Add(uc);
}
}
}
protected void myTreeViewMenu_MenuChanged(string e)
{
this.myPanel.Controls.Clear();
switch (e)
{
case "link1":
var cc1 = "~/Content1.ascx";
this.currentControl.Value = this.Server.HtmlEncode(cc1);
var uc1 = this.LoadControl(cc1);
this.myPanel.Controls.Add(uc1);
this.lblMessage.Text = "Updated from: link1";
break;
case "link2":
var cc2 = "~/Content2.ascx";
this.currentControl.Value = this.Server.HtmlEncode(cc2);
var uc2 = this.LoadControl(cc2);
this.myPanel.Controls.Add(uc2);
this.lblMessage.Text = "Updated from: link2";
break;
default:
this.lblMessage.Text = "Updated from default: " + e;
break;
}
}
ASCX
<h1>Content 1</h1>
<asp:TextBox runat="server" ID="txt" />
<asp:Button Text="Process data..." runat="server" OnClick="button_Click" />
<asp:Button Text="Just post" runat="server" />
<asp:Label ID="lblMessage" runat="server" />
ASCX Code Behind
protected void button_Click(object sender, EventArgs e)
{
this.lblMessage.Text = this.txt.Text;
}
You can simply copy-paste this code to test it yourself, this should work
Jupaol's answer works fine but 1 thing need to mention, I came across the problem after implemented Jupaol's idea, the first time I called the user control immediately after I click menu, the button with in the ascx works fine, but if I switch to 2nd one, first click of the button on the 2nd control will not fire on first click, this is because we do not have a "static" ID of the control. It took me almost 3 days to finally figure out why this is happening. so here's part of my code to make. I'm leaving this message in hope that anyone who read this afterwards will make the use of it.
if (!string.IsNullOrEmpty(controlPath))
{
PlaceHolder1.Controls.Clear();
UserControl uc = (UserControl)LoadControl(controlPath);
/**note below LastLoadedControl is anything that could
* be unique to the called control so every time when call back
* it will not confuse the back end so the first fire of eg. a button
* on that loaded control will work
*/
uc.ID = LastLoadedControl;
PlaceHolder1.Controls.Add(uc);
}
I'll also need to thank Jupaol's great contribution so that I can get my site running.

DropDownList's SelectedIndexChanged event not firing

I have a DropDownList object in my web page. When I click on it and select a different value, nothing happens, even though I have a function wired up to the SelectedIndexChanged event.
First, the actual object's HTML code:
<asp:DropDownList ID="logList" runat="server"
onselectedindexchanged="itemSelected">
</asp:DropDownList>
And this is that function, itemSelected:
protected void itemSelected(object sender, EventArgs e)
{
Response.Write("Getting clicked; " + sender.GetType().ToString());
FileInfo selectedfile;
Response.Write("<script>alert('Hello')</script>");
foreach (FileInfo file in logs)
{
if (file.Name == logList.Items[logList.SelectedIndex].Text)
{
Response.Write("<script>alert('Hello')</script>");
}
}
}
None of the Responses appear, and that portion of JavaScript is never run. I've tried this on the latest 3.6 version of Firefox, as well as Internet Explorer 8. This is being served from a Windows Server 2003 R2 machine, running ASP.NET with the .NET Framework version 4.
Set DropDownList AutoPostBack property to true.
Eg:
<asp:DropDownList ID="logList" runat="server" AutoPostBack="True"
onselectedindexchanged="itemSelected">
</asp:DropDownList>
try setting AutoPostBack="True" on the DropDownList.
I know its bit older post, but still i would like to add up something to the answers above.
There might be some situation where in, the "value" of more than one items in the dropdown list is duplicated/same. So, make sure that you have no repeated values in the list items to trigger this "onselectedindexchanged" event
Add property ViewStateMode="Enabled" and EnableViewState="true"
And AutoPostBack="true" in drop DropDownList
Also make sure the page is valid.
You can check this in the browsers developer tools (F12)
In the Console tab select the correct Target/Frame and check for the [Page_IsValid] property
If the page is not valid the form will not submit and therefore not fire the event.
For me answer was aspx page attribute, i added Async="true" to page attributes and this solved my problem.
<%# Page Language="C#" MasterPageFile="~/MasterPage/Reports.Master".....
AutoEventWireup="true" Async="true" %>
This is the structure of my update panel
<div>
<asp:UpdatePanel ID="updt" runat="server">
<ContentTemplate>
<asp:DropDownList ID="id" runat="server" AutoPostBack="true" onselectedindexchanged="your server side function" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
Instead of what you have written, you can write it directly in the SelectedIndexChanged event of the dropdownlist control, e.g.
protected void ddlleavetype_SelectedIndexChanged(object sender, EventArgs e)
{
//code goes here
}

FileUpload in FormView inside an UpdatePanel

The Scenario:
I have an ASP.Net webpage which I intend to use for letting the user(not the real users, but content manager basically) insert and edit the records in a table using a FormView. This FormView is inside an UpdatePanel, as I'm also using cascading dropdownlists to let the user select some values.
Now, this FormView also contains 4 FileUpload controls, and as you might know that these fileupload controls require a full postback since most browsers do not let Javascript access the disk. So, this problem would have been solved by doing something like:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<Triggers>
<asp:PostBackTrigger ControlID="InsertButton" />
<asp:PostBackTrigger ControlID="UpdateButton" />
</Triggers>
<ContentTemplate>....</ContentTemplate>
</asp:UpdatePanel>
Edit: Forgot to add that the fileuploading takes place in the OnUpdating and OnInserting events of the SqlDataSource.
The Problem:
Since the InsertButton and the UpdateButton reside inside the Formview, I cannot directly access their ID's through markup. And MSDN says that:
Programmatically adding
PostBackTrigger controls is not
supported.
Please suggest some solution to make this work. Any insight on the matter is highly appreciated. Thanks.
P.S.- A workable solution for me was to set the UpdatePanel's PostBackTrigger as the whole FormView itself:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<Triggers>
<asp:PostBackTrigger ControlID="FormView1" />
</Triggers>
<ContentTemplate>....</ContentTemplate>
</asp:UpdatePanel>
But now due to a bit of change in requirements, this solution(if you call it a solution) is not acceptable.
Have you given a though about using Iframe for doing the postback ? something like:
<iframe name="uploader" id=uploader
src="uploaderSender.aspx?AllowedExtension=<%= AllowedExtension %>&StoringPath=<%= StoringPath %>&StoringFileName=<%= StoringFileName %>&OldFileName=<%= OldFileName %>&MaximumSize=<%= MaximumSize %>"
width="450" height="50" frameborder=0 scrolling=no >
</iframe>
with uploaderSender.aspx like :
<form action="UploaderReceiver.aspx" method="post" enctype="multipart/form-data">
<input type="file" name="file" id="file" onchange="document.getElementById('IsFileUploading').style.visibility = 'visible'; document.forms[0].submit()"/>
<span id="IsFileUploading" style="visibility: hidden">
<asp:Image ID="Image1" runat="server" ImageUrl="~/immagini/Ajax-loader.gif" />
</span>
</form>
and UploaderReceiver.aspx like :
protected void Page_Load(object sender, EventArgs e)
{
//if there is one file to process
if (Request.Files.Count > 0)
//create the folder if it does'nt exists and returns the local path to get it
string StoringPathToBeSaved = StoringPath.GetFolderPath();
// append the name of the file to upload to the path.
StoringPathToBeSaved = StoringPathToBeSaved + StoringFileName + Extension;
Request.Files[0].SaveAs(StoringPathToBeSaved);
}
this is just bits of code just for you to figure out if you would be interested in this way of dealing with the upload, I can give you more if you want after.
see you, and good luck with your code,
Yay!! Finally got it to work!
Here's How:
Well contrary to what MSDN says, we can in fact add PostBack Triggers Programmatically. Not necessarily to the UpdatePanel, but to the ScriptManager.
After hours of playing around, here's what worked:
We are not able to access controls inside a FormView, untill the template has been rendered, so we can only add postback triggers after the formview's OnDataBound Event.
protected void FormView1_DataBound(object sender, EventArgs e)
{
if (FormView1.CurrentMode == FormViewMode.Edit)
{
LinkButton lb = (LinkButton)FormView1.FindControl("UpdateButton");
ScriptManager.GetCurrent(Page).RegisterPostBackControl(lb);
}
//Similarily you can put register the Insert LinkButton as well.
}
And now, if your UpdatePanel causes ConditionalUpdate, you can do something like this to make it work:
The Markup:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>..
<EditItemTemplate>
...
<asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" OnClick="Cause_PostBack"CommandName="Update">Update</asp:LinkButton>
...
</EditItemTemplate>
..</ContentTemplate>
</asp:UpdatePanel>
CodeBehind:
//call this function as the OnClick Event Handler for the Controls you want to register as
//triggers.
protected void Cause_PostBack()
{
UpdatePanel1.Update();
}
Otherwise, if your situation allows it(as mine does), just set the UpdatePanel's UpdateMode="Always"
This is old, but was trying to solve another problem and ran into this. This wasn't my problem, but here's an alternative for anyone new who runs into this as well.
You stated your problem as:
Since the InsertButton and the UpdateButton reside inside the Formview, I cannot directly access their ID's through markup
You actually can access their ID's through markup to use as the ControlID in the PostBackTrigger. You just have to use the button's name that is created in the page html mark-up as the ControlID. You can find the name created by viewing the page source when you're viewing the page in the browser. It typically is the name of the FormView + $ + name of the button.
For example, let's say you have a FormView named "FormView1" that contains an Insert button which you gave the ID of "btnInsert" during design. If you open up your page in the browser to view it live and then view the page's source, you'll notice that the html mark-up of the button will actually be given the name "FormView1$btnInsert".
Use that name as the ControlID in your PostBackTrigger and your update panel will work.
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<Triggers>
<asp:PostBackTrigger ControlID="FormView1$btnInsert" />
</Triggers>
<ContentTemplate>....</ContentTemplate>
</asp:UpdatePanel>

TemplateField button causing GridView Invalid Postback

Ok, so I've got a template field in a gridview that contains just a simple button...
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Administration.aspx.cs"
Inherits="Administration" %>
<%# Register TagPrefix="ajaxToolkit" Namespace="AjaxControlToolkit" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Keywords Administration</title>
</head>
<body class="popupbody">
<form id="form1" runat="server">
<ajaxToolkit:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server" EnablePartialRendering="true" CombineScripts="false"></ajaxToolkit:ToolkitScriptManager>
<asp:Label ID="AddLabel" runat="server">Add a Keyword</asp:Label>
<br />
<asp:TextBox ID="AddTextBox" runat="server" />
<asp:Button ID="AddButton" Text="Add" runat="server" OnClick="AddKeyword_Click" />
<asp:GridView ID="KeywordsGridView" AllowPaging="false" AutoGenerateColumns="false" BackColor="white"
GridLines="None" HeaderStyle-CssClass="Table_Header" RowStyle-CssClass="Table_Style"
OnRowDataBound="RowBound" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Button runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="References" SortExpression="References" HeaderText="Total References" />
<asp:BoundField DataField="Keyword" SortExpression="Keyword" HeaderText="Keyword" />
</Columns>
</asp:GridView>
</form>
</body>
</html>
Whenever I click the button I get the error...
Invalid postback or callback argument. Event validation is enabled using
<pages enableEventValidation="true"/> 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.
I've found a decent amount of articles referencing this issue, including a couple on SO, for example...
Invalid postback or callback argument. Event validation is enabled using '<pages enableEventValidation="true"/>'
and...
Invalid postback or callback argument
I might just be misunderstanding, but as far as I can tell they don't really help me. How do I get this to go away without setting enableEventValidation="false"?
EDIT Posted all the code for my page.
I know this post is old, but I also had this problem recently.
After checking the how the code was generated for the asp:ButtonField and also for the asp:Button that I have added in an ItemTemplate I discovered quite a big difference:
asp:ButtonField:
input type="button" onclick="javascript:__doPostBack('ctl00$ctl00$cphMain$cphContent$gvEmails','SendFromBatch$0')" value="Continue">
asp:Button:
input id="ctl00_ctl00_cphMain_cphContent_gvEmails_ctl02_btnCont" type="submit" onclick="FreezeScreen('Emails are being sent...');" value="Continue" name="ctl00$ctl00$cphMain$cphContent$gvEmails$ctl02$btnCont">
The Type was the problem! So, after i changed the UseSubmitBehavior from "Submit" to "False" I did not get the error anymore.
EDIT:
I recently wanted to change from the normal btns to imgBtns so that I can save some space and also make the gridview nicer :D. Of course I had the same problem popping up and the imagebtn does not have UseSubmitBehavior property, so I started looking after a solution.
Found the following (The code below is in a UserControl).
1) Bind in !IsPostBack
2) Register the usercontrol itself in the Render
and everything works just as planned - no validation errors.
protected void Page_Load(object sender, EventArgs e)
{
OnLoadingEvent(new EventArgs());
if (!Page.IsPostBack)
{
gvEmails.DataSource = odsEmails;
try
{
gvEmails.DataBind();
}
catch (Exception)
{
}
}
if (!writeText) divWriteEmail.Visible = false;
}
protected override void Render(HtmlTextWriter writer)
{
Page.ClientScript.RegisterForEventValidation(this.UniqueID);
base.Render(writer);
}
EDIT:
I was playing around with the code above and asked myself, what if you actually need to rebing your objectdatasource - what happens then? Well the code above will not work if you rebind in the page load, because the gridview will be rebound again when you click a btn in the gridview's row and it will not be recognized as being generated on the server. Fair and square, but how to avoid this behaviour? Well... i figured out a way, maybe not the best but it does the trick.
Actually, you do not want to rebind the gridview when you click a btn on the gv's row... but how do we know that since the page load method is first called? Well, actually i do not want to rebind the gridview if the select param of the object data source do not change. So, I keep the select param of the objectDataSource in the session view and I rebind my gridview only when one of them changes - this behaviour is only during the PageLoad event. In order to see latest rows i click refresh and get the latest rows with no problem and at the moment i click a gvRow btn, the error dissapears.
To make all of this happen you have to
Directly call the .Select() of the object data source
Catch the OnSelecting event from the datasource, save the select param set the e.Cancel = true
Check if the select param are different and then bind the gridview and this time when catching the OnSelecting you have to set e.Cancel = false in order to retrieve the data from the DB - only one time.
Hope this helps!
This fellow found a solution to a similar problem (scroll down to about the 4th comment), which was to set unique id's for the GridView buttons.
I had the similar error today but with a different solution. I've worked with gridviews for years now and never had the issue so I figured it must be something stupid. Turns out I had forgotten to put my code that loads the gridview into a if(!Page.IsPostBack) block which caused the button to be recreated after I clicked it, thus causing the error. Placing the loading code in said block eliminated the issue.
You need to give your button an ID. Just a runat="server" does not meet the minimum information that needs to be provided for a server control to be created.

Why aren't all controls initialised at the event handling point of the ASP.NET page lifecycle?

I have a user control embedded in a web part. It has the following snippets of code:
protected TextBox searchTextBox;
protected Button goButton;
protected Button nextButton;
protected Repeater pushpins;
protected Label currentPageLabel;
protected void goButton_Click(object sender, EventArgs e)
{
// Do stuff
}
<asp:TextBox ID="searchTextBox" runat="server" />
<asp:Button ID="goButton" runat="server" Text="Go" OnClick="goButton_Click" />
<asp:Repeater ID="pushpins" runat="server" EnableViewState="false">
<ItemTemplate>Blah</ItemTemplate>
</asp:Repeater>
<asp:Label ID="currentPageLabel" runat="server" />
<asp:Button ID="nextButton" runat="server" Text=" >> " OnClick="nextButton_Click" />
(There is no OnLoad or CreateChildControls method.)
If I place a breakpoint on the first line of goButton_Click, I find:
searchTextBox: initialised
goButton: initialised
nextButton: NULL
pushpins: initialised
currentPageLabel: NULL
Why are some controls initialised and others not? How do I get around this if I'd like to update the Text property on currentPageLabel?
Update:
I've placed breakpoints all the way through the page life cycle and found that nextButton and currentPageLabel are never initialised. The breakpoints were placed at OnLoad, CreateChildControls, goButton_Click, OnPreRender, Render and OnUnload.
Is it possible you've inadvertently got local variables named currentPageLabel and/or nextButton declared somewhere? The compiler will happily allow this...
This is especially common in a move from ASP.NET 1.1 to 2.0 or higher, since the way the designer defined these controls changed.
The problem was that all of the controls that weren't being initialised were inside a HeaderTemplate within a Repeater control. (To save space I didn't paste all of my code into the question, dang it.)
I moved them out and the problem is resolved. Obviously controls in the HeaderTemplate are instantiated by the Repeater and do not follow the normal page life cycle.

Resources