Why controls don't behave on postback as expected? - asp.net

Please forgive me if this has been asked before or if I am not asking correctly. I am new to programming and working on a school assignment.
Assignment: Create a web application project with 2 textboxes and a button control
a) On changing the text in field one the text in field 2 should blank.
b) On pressing the button the text from field one should be put in field 2
c) All event should be handled on the server side, so no javascript. (Confirmed this with teacher, NO JAVASCRIPT)
Here is the problem:
The page loads with both blank text boxes. I enter text in textbox1, press ok, page reloads but there is nothing in textbox2 (its supposed to copy contents of textbox1). If I press the submit button again, the text copies to textbox 2 as it should.
If I change the text in textbox1, leave focus, page reloads and blanks box 2 as it should. If I press submit button, it copies the text as it should.
I simply cannot get it to work properly the first time the page is loaded.
Here is the code for default.aspx:
<%# Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body style="height: 141px">
<form id="form1" runat="server">
<div>
</div>
<asp:TextBox ID="TextBox1" runat="server" AutoPostBack="True"></asp:TextBox>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<p>
<asp:Button ID="Button1" runat="server" Text="Submit" />
</p>
</form>
</body>
</html>
And here is the code from default.aspx.vb:
Partial Class _Default
Inherits System.Web.UI.Page
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
TextBox2.Text = TextBox1.Text
End Sub
Protected Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
TextBox2.Text = ""
End Sub
End Class
I know that when I am entering text into textbox1 for the first time that it is triggering the event for textchanged, but it seems to be happening in the wrong order that I need.
What am I not doing right?
Please let me know if you need any other information.

Generally speaking, it is incorrect to say "NO JS" because Postback is JS-invoked event. With no JS at all it is not possible because you can't cause Postback by typing into textbox. And TextChange event happens on postback when Asp.Net determined that content of TB has changed.
So if you want to type with postback you need minimal JS as described here
You need to remove AutoPostBack from your TextBox1 because it causes postback when focus moves from textbox. This is the problem. Your button is never pressed on the first pass hence your TextBox2.Text = TextBox1.Text never runs on the first time. Second time you already pressing the button, therefore code works.

Related

How do I prevent __DoPostBack refreshing an ASPX page?

I have a JS function in an ASPX page that performs a __doPostBack to a vb.net code behind. The problem is that it is forcing the page to refresh. How can I prevent this? My code below...
JS:
__doPostBack('', 'test');
VB.NET:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack Then
Select Case Request.Form("__EVENTARGUMENT")
Case "test"
RadMediaPlayer1.Source = url
End Select
End Sub
Thanks!
There is one easy way, and then one hard way.
The first issue? asp.net web pages are in fact designed to near ALWAYS have and endure post-backs.
This quite much means that any button, any combo box, or just about anything on that page to run some code behind WILL cause a page post-back.
And thankfully due to automatic "view state" management, most controls, and even a grid view, or even a combo box selection will correctly maintain its values for you (its view state).
So, if you don't want the whole page to post back and refresh?
Then you can drop in a plane jane asp.net button, and say whatever it is you want to "only update", then try using what is called a update panel.
Try a quick test page like this:
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" Text="Button" />
</div>
</form>
And our code behind like this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
TextBox1.Text = Date.Now
System.Threading.Thread.Sleep(700)
End Sub
Now, I put in a 3/4 of second delay - just to help you see the effects of this (you don't want that delay sleep() in your actual code.
Ok, now run the above page, click on the button. You see the traditional post-back, you see the browser "spinner"/wait occur, and then the text box is updated.
Now, lets use what is called a update panel - and I am going to suggest you try one.
You can even dump/drop the JavaScript you have now.
So, you have to drop into the page a script manager, and then move your content inside of he update panel. It will now look like this:
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<div>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" Text="Button" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
Give above a try - note how the page don't post-back any more? How cool is that!!!
So, add update panel, content template. And move your button, and the adMediaPlayer1 into that panel.
You don't even need to adopt any JavaScript here. Drop in a plane jane button, and just have normal code behind for that button. Say like this:
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
RadMediaPlayer1.Source = "some real url goes here"
End Sub
A few things:
While this looks, feels and appears to NOT do a post back and the .net system will wire this up for you automatic - VERY much like a ajax call?
Don't put too much inside of those update panels.
and keep in mind, while this does not seem to do a post back? In fact this results in what we call a "partial" post back. The page load event even will fire.
Note that code behind CAN ONLY now modify controls inside of that update panel. Other controls on the page are off limits. (unless you move them into that update panel also).
But, dump your JavaScript button or code for the post back. Just move in the media control and your button to inside of that up date panel. Give this a try - you not see a post back - you not see the browser "spinner"/wait run at all.
This feature is great - but a not a cure all.
The next way to do this?
Is you can setup what is called a ajax call. This can call code behind, but keep in mind the code behind can't update controls on the page (due to no post-back). If you don't do a post-back, then code behind can't touch controls on the page.
This would suggest that you have a client side button - click on it, it runs JavaScript, calls some code behind, code behind returns a result, and then in JavaScript you stuff/change the URL of the given control. Since you changing that URL in pure JavaScript at this point? You probably don't even need to write or call code behind anyway.
but, try the update panel - they are very useful. But, keep in mind behind, the .net system is doing a bit of fakery to achieve this goal, and what a partial page post- back does occur.
Edit: pass value from js and click button
So, as noted, if you have a post back, you get page refresh!!! - that's what the command does and means!! So, you can't say I dont want to post back and not refresh the page, and then do a post back!!!
However, as noted, your js code is "obviously" a much larger example, and you sharing of JUST the __DoPostBack() in js is as you noted a larger set of code and routines here.
However, I still suggest you use a update panel.
You can keep 99% of your js code now, and just remove the _dopost back.
Move your case statement code to a button. (yes, a button click code stub).
What we THEN do is this:
The js code can figure out and do whatever it needs. Obviously we reach a point in which a VALUE of some type has to be passed to the server. And then what we will do is then use js code to CLICK the button - the ONE inside of the update panel. This will and should prevent a page refresh. And we pass the value by using a asp.net hidden field control (you could even use a hidden text box - but it don't matter - hidden field is probably better).
So, the pattern, and code will look like this:
We drop a button, hidden field, and that other video or whatever control is is the page - all inside the update panel.
then your js code? It runs, gets the final value. We shove that value into a hidden field control, and then use js to click the button - also inside of that panel.
Thus, you move your on load code + case statement to the button click code.
Like this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' get value passed from js
Dim strMyValue As String = Me.HiddenField1.Value
Debug.Print(strMyValue)
Select Case strMyValue
Case "test"
Case "zoo"
Case "my fun test"
End Select
End Sub
And the markup is this:
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<div>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" Text="Button" ClientIDMode="Static" />
<br />
<asp:HiddenField ID="HiddenField1" runat="server" ClientIDMode="Static" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:Button ID="Button2" runat="server" Text="js post back"
OnClientClick="mypost();return false;"
/>
<script>
function mypost() {
// set value to pass to button click
$('#HiddenField1').val("my fun test")
$('#Button1').click()
}
</script>
</div>
So, in place of your doPostback, you set the hidden field, and then with js click the button. (once you get this workng, then hide the button with style="display:none"
Of course, you proably have a bunch of postback in your code.
So, make a js function called MyPostBack, say like this:
function MyPostBack(sValue) {
// set value to pass to button click
$('#HiddenField1').val(sValue)
$('#Button1').click()
}
Now, you can replace all your _DoPostBack('', 'test')
With MyPostBack('test')
So, in the update panel, put the hidden field, the button, and that other control. And your js code will now "click" that button in the panel.
Note that the js code above does assume you using jQuery. However, you can code in pure js, and not necessary use jQuery short hand as I did above.

UpdatePanel breaks after adding UpdateProgress

I have some code that contains a panel where I put an ASP chart from codebehind. Below the panel I placed a button with a postback event that changes some parameter of that chart.
Here is a simplified version of the code:
...
<asp:UpdatePanel ID="udp" runat="server">
<ContentTemplate>
<asp:Panel ID="pnl_chart" runat="server" />
<asp:Button ID="btn_chart" UseSubmitBehavior="false" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
...
And the code behind:
Private Property AltChart As Boolean
Get
If Me.ViewState("simulador_avanzado") Is Nothing Then
Return False
End If
Return ToBool(Me.ViewState("simulador_avanzado"))
End Get
Set(value As Boolean)
Me.ViewState("simulador_avanzado") = value
End Set
End Property
Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
...
If IsPostBack AndAlso ToStr(Me.Request("__EVENTTARGET")).Contains("btn_chart") Then
AltChart = Not AltChart
End If
Dim cht as New Chart
'Build the chart...'
pnl_chart.Controls.Add(cht)
...
End Sub
This works like a charm, but when I add an UpdateProgress the PostBack stops working. Whenever I click the button, the UpdateProgress is shown for 2-3 seconds (exactly what it takes to do the PostBack) but then it hides and the UpdatePanel content isn't refreshed.
This is the new code:
...
<asp:UpdatePanel ID="udp" runat="server">
<ContentTemplate>
<asp:Panel ID="pnl_chart" runat="server" />
<asp:Button ID="btn_chart" UseSubmitBehavior="false" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdateProgress ID="udpro" AssociatedUpdatePanelID="udp" DynamicLayout="false" runat="server">
<ProgressTemplate>
<div class="udp_progress">
</div>
</ProgressTemplate>
</asp:UpdateProgress>
...
I debugged the partial postbacks and the code behind is working as intended, it updates the AltChart variable and the chart itself.
To put it simple: UpdatePanel partial postback works perfectly, but when I add an UpdateProgress bound to it, its content isn't updated on partial postbacks.
Update: I'm getting the next client error:
SCRIPT5022: Sys.InvalidOperationException: Could not find UpdatePanel with ID 'ctl00_Body_ctl02_udp_button'. If it is being updated dynamically then it must be inside another UpdatePanel.
Apparently the js generated by the UpdateProgress is being cached. The UpdatePanel with ID udp_button is from a previous version of the code and it's no longer there (I had the button outside the UpdatePanel and I wrapped it with its own UpdatePanel to make the UpdateProgress aware of the async postback, following this example, now I simply put it inside the chart's UpdatePanel).
Clearing the browser cache does not seem to work (as well as using a different browser).
UPDATE 2: OK, I was mistaken.
udp_button is another UpdatePanel present on the page, it's inside a user control and I hadn't noticed it. I'll try to place some conditional UpdateModes on both UpdatePanels to see if I can prevent the UpdateProgress from updating the wrong UpdatePanel.
I did what I mentioned on the Update 2 and it worked!
Apparently, the javascript code generated by the UpdateProgress control tries to update all UpdatePanels on the page affected by the async postback, and couldn't find an UpdatePanel that was inside a web user control (the ID it was using to look for the panel didn't match the panel ClientID).
Solution: Establish the property UpdateMode="Conditional" for the UpdatePanel inside the web user control, and make it update only when it's needed. This way the web user control isn't updated during the async postback generated by the button, and the UpdateProgress' javascript doesn't try to find it.

ASP.NET GridView empty on postback

Having an issue with an ASP.NET GridView is empty on postback that I need some help with. I think it may have something to do with the ViewState not being setup. Anyhow I originally had the code working on single user-form until I refactored code.
Now to paint the picture I have now both a master page and a base form. My master page has the place holder and on my actual user-form I have placed the GridView within the place holder bounds as follows:
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolderMainBody" Runat="Server">
<asp:GridView ID="data" runat="server" AutoGenerateColumns="false" EnableViewState="true" ...>
...
</asp:GridView>
</asp:Content>
One of fields in the GridView is an editable comments field mutli-line textbox (the rest are non editable):
<asp:TemplateField HeaderText="Comments">
<ItemTemplate>
<asp:TextBox ID="TextBoxComments" runat="server" TextMode="MultiLine" Rows="4" Columns="40" Text='<%# Bind("Comment")%>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="TextBoxCommentsEdit" runat="server" TextMode="MultiLine" Rows="4" Columns="40" Text='<%# Bind("Comment")%>' />
</EditItemTemplate>
</asp:TemplateField>
I edit one of the rows and click a submit button to postback. The GridView has 10 rows to enter into however on postback there are zero rows so my saving is lost!
My base form contains the code in the OnInit event to load the submit button and thus also handles the click event.
My OnLoad event I call the base Onload which inturn calls my user form's Page_Load handler code which has one line of code namely:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
MyBase.data = Me.data
End Sub
and in the BaseForm is declared as:
Protected WithEvents data As GridView
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
If Not Page.IsPostBack Then
...
BindData(...)
...
End If
End Sub
in this way I can also handle all GridView events in the BaseForm.
So somewhere between the master/baseform/userform/viewstate relationship my GridView data is lost on PostBack. Any ideas?
On your Page_Load, bind the data only if IsPostBack is false.
You click on submit button that submit button fire RowUpdating event and that event contain query for update database table and after executed update query call BindData() function in your code .
Three in row I think for myself answering my own question - hooray! I do not know if that makes me intelligent or dumb because I have to search for more that a day to find a solution. Perhaps I did not give out enough information or it was not clear and this is what happens when you do things for the first time and you do not have a clue what you are doing. The vital information which was maybe not implied but hinted at, which I will spell it out for anyone else that might have the same problem, is I left out mentioning in my OnInit method I call the following code:
Dim cpl As ContentPlaceHolder = Master.FindControl("ContentPlaceHolderFooter")
btnUpdate = New Button
btn.ID = "btnUpdate"
cpl.Controls.Add(btnUpdate)
I know the purest will say why did you not add the button to the footer of the grid as opposed to an additional content placeholder in the master page - well with egg on my face I didn't.
Anyhow I moved the code above to the CreateChildControls overridable method and I also required an additional call to EnsureChildControls in my OnLoad event so my OnInit method with emphasis disintegrated!##%^* Why? Well the answer was hinted at within the answer to the other question asked on this site I mentioned in my second comment to "Rajan Chauhan" that I checked out and that is apparently whenever you iterate through the collection of controls you mess with the ViewState (hey I am just re-iterating what was said in the other post I have no authority on the matter) before it gets loaded so calling Master.FindControl is a no-no inside OnInit!
However, saying all that my RowUpdated event does not fire as I am actually editing in view mode because of my ItemTemplate markup so I will stick with what I have as my btnUpdate_Click event still works as before i.e. it does some magical code that I found on some other site that checks each row one by one for change of data and then updates that particular row only. Well I can as there is only 10 rows at most so I do not overload the ViewState too much and if it is important to know I also use paging so in reality I have more than 10 rows but did not want to mention that as I thought that might add to the confusion.

How to set default properties of a control programmatically without it bloating the viewstate

I have a page with a number of controls on. Some of the control properties/values are loaded from a database. Others are eg. date combo boxes with numbers 1-31, years 1900-2012 etc. I would like to populate the combo boxes in a for loop, but I've noticed that if I do that even as early as Page_Init, all the values get entered into the viewstate. I don't want to disable viewstate on those controls since I need it to maintain the value across postbacks when they are hidden.
Effectively, I'm asking how ASP.NET determines what the default values of the control are - it doesn't put values in to the viewstate if I enter them in the markup and I was wondering if anyone knows a way to reproduce that programmatically?
test2.aspx
<%# Page Language="VB" AutoEventWireup="false" CodeFile="test2.aspx.vb" Inherits="test2" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:DropDownList ID="ddlTest" runat="server"></asp:DropDownList>
</div>
</form>
</body>
</html>
test2.aspx.vb
Partial Class test2
Inherits Page
Protected Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init
If Request("addvals") IsNot Nothing Then
For i As Integer = 0 To 1000
ddlTest.Items.Add(i)
Next
End If
End Sub
End Class
Have just found a duplicate of this - it appears that it isn't possible...
Is it possible to set asp.net control property values in code behind without adding it to viewstate?
According to this article (linked in the duplicate question) You can create the control dynamically and databind it before adding it to the controls collection. This will be good if your databound control does not use excessive item templates (i.e. if it is DropDownList and not a GridView). Another option is to disable the ViewState on the control and make sure you save the state of the hidden controls manually in the ViewState dictionary.
Values added during the Init phase are not persisted to ViewState (they are added to the ViewState StateBag, but not marked as dirty).
If you want to set default properties while ViewState is being tracked (e.g. during the Load phase or later), then set them before adding the control to the Page's control tree if you don't want them to be persisted to ViewState. E.g.
Label label1 = new Label();
label1.Text = "Some text" // Not persisted to ViewState
Page.Controls.Add(label1);
Label label2 = new Label();
Page.Controls.Add(label2);
label2.Text = "Some text" // Persisted to ViewState

How do I prevent the closing of modal popup window(ModalPopupExtender) on postback?

I'm using Microsoft AjaxControlToolkit for modal popup window.
And on a modal popup window, when a postback occurred, the window was closing. How do I prevent from the closing action of the modal popup?
Put you controls inside the update panel. Please see my sample code, pnlControls is control that holds controls that will be displayed on popup:
<asp:Panel ID="pnlControls" runat="server">
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Button ID="TestButton" runat="server" Text="Test Button" onclick="TestButton_Click" />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
This will do the job for you :)
Best regards,
Gregor Primar
You can call Show() method during postback to prevent the modal popup window from closing
MyModalPopoupExtender.Show()
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
// reshow
MyModalPopup.Show()
}
}
I guess that works but not in my case. I've a user control that opened in a modal popup and this user control makes postback itself. So in that user control I've no modal popup property.
I guess, I've to create an event for my user control, and the page that opens the modal popup have to reopen it in this event.
Was having this same problem keeping a modal open during postbacks.
My solution:
Use EventTarget to determine if the postback is coming from a control in the modal and keep the model open if it is. The postback can come from a control in the modal iff the modal is open.
In the load event for the page control containing the modal. Determine if the postback is from
a child of mine. Determine if it is from the control that is in the modal panel.
Protected Sub Control_Load(sende As Object, e As EventArgs) Handles Me.Load
If IsPostBack Then
Dim eventTarget As String = Page.Request.Params.Get("__EventTarget")
Dim eventArgs As String = Page.Request.Params.Get("__EventArgument")
If Not String.IsNullOrEmpty(eventTarget) AndAlso eventTarget.StartsWith(Me.UniqueID) Then
If eventTarget.Contains("$" + _credentialBuilder.ID + "$") Then
' Postback from credential builder modal. Keep it open.
showCredentialBuilder = True
End If
End If
End If
End Sub
In prerender check my flag and manually show the modal
Protected Sub Control_PreRender(ByVal sende As Object, ByVal e As EventArgs) Handles Me.PreRender
If showCredentialBuilder Then
_mpeCredentialEditor.Show()
End If
End Sub
Like you prolly already know, the modal popup is clientside only, yeah you can gather informations in it during the postback, but if you do a postback he will hide 100% of the time.
Of course, like other proposed, you can do a .show during the postback, but it depends on what you need to do.
Actually, I don't know why you need a postback, if it's for some validations try to do them clientside.
Could you tell us why you need to do a postback, maybe we could help you better ! :)
Following previous case...
In Simple.aspx, user has to enter the name of a company. If user don't remember name of the company, he can click a button which will open a pop up modal window.
what I want to do in the modal window is permit the user to do a search of a list of companies. He can enter a partial name and click search. Matches will be shown in a list below. He can click in an item of the list and return. If company does not exist, he can click a button 'New' to create a new company.
So, as you can see, I want a lot of functionality in this modal window.
Thanks!
JC

Resources