I have the following aspx page:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="index" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="lblStatus" runat="server" Text="Label">
</asp:Label><asp:Button ID="btnRun" runat="server" Text="Button" onclick="btnRun_Click" />
</div>
</form>
</body>
</html>
The codebehind is:
public partial class index : System.Web.UI.Page
{
protected void btnRun_Click(object sender, EventArgs e)
{
CP CPObj = new CP();
lblStatus.Text = "Starting process..";
CPObj.run();
lblStatus.Text = "Process done.";
}
}
The class needs to do some work (about a minute).
When I click the button, the label does not change and only after the class completes the job the label is changed to "Process done.".
I've looked for a solution for a really long time but could not find a clear and straight forward answer.
I've tried to run the class as a thread and got the same result.
public partial class index : System.Web.UI.Page
{
protected void btnRun_Click(object sender, EventArgs e)
{
CP CPObj = new CP();
Thread oThread = new Thread(new ThreadStart(CPObj.run));
lblStatus.Text = "Starting process..";
oThread.Start();
while (!oThread.IsAlive) ;
while (oThread.IsAlive)
{
Thread.Sleep(1000);
}
lblStatus.Text = "Process done.";
}
}
Using JavaScript seems problematic since I already have an onClick call (not sure if I'm correct here).
I'd really appreciate a response.
Thanks!
Nadav
Web pages aren't like traditional web forms.
You can't set a label to some value and then within the same callback change that value to something else and have both appear.
What you need to do is use some ajax. The simple way would be to add an update panel and go that route. Basically, you would set the label via javascript to "starting process..." then let the panel change the label once the callback is complete.
Alternatively, you could do it without ajax; but again you set the label via some javascript first. Then let your call back routine over write it.
I think you need to read about page life cycle. Is nice you are updating your label, but since this is web, your data will no go back to the browser until all the code run. So you can't update a label that doesn't exist yet on a page you are not yet sending to the browser ;)
I think JS is the solution for you (not an expert on that field) or maybe some ajax that will query the process runtime, and the process running on another thread?
Related
I am working on a project in C# .NET that allows me only one form in the .aspx file.
<form id="form1" runat="server" action="#1">
How can I change the form action through the C# code in a method?
I have tried this:
protected void Button1_Click(object sender, EventArgs e)
{
form1.Action = "#2";
}
but it didn't work. Thanks in advance...
Based on the comments to you question. asp:Panel Controls could help you out.
A very rough example
ASPX:
<form id="form1" runat="server">
<asp:Panel id="Form1" runat="server">
<!-- Form 1 Stuff -- >
<asp:Button ID="Button1" runat="server" Text="Submit"
OnClick="Button1_Click" />
</panel>
<asp:Panel id="Form2" runat="server" Visible="false">
<!-- Form 2 Stuff -- >
<asp:Button ID="Button2" runat="server" Text="Submit"
OnClick="Button2_Click" />
</panel>
</form>
C#
protected void Button1_Click(object sender, EventArgs e)
{
//HIde "Form"1
Form1.Visible = false;
//Show "Form"2
Form2.Visible = true;
//Do other stuff
}
protected void Button2_Click(object sender, EventArgs e)
{
//Do Final Processig
}
Also look at the DefaultButton property of the Panel
(Moving this to the top because it's an answer to the newly understood question. It's not how to change the form action, but how to have multiple forms.)
If you want a server form on a page that already has a server form then perhaps that second "form" should be a User Control. That way it sits inside the host page's server form but doesn't require its own form. And it's self-contained, able to contain whatever logic it needs when handling a postback.
Here's an example of a simple User Control. You can create one from Add > New Item > Web > Web Forms User Control.
<%# Control Language="C#" AutoEventWireup="true"
CodeBehind="OtherForm.ascx.cs" Inherits="WebApplication1.OtherForm" %>
<label for="<% = OtherFormTextInput.ClientID %>">
This is some other form on the same page
</label>
<asp:TextBox runat="server" ID="OtherFormTextInput"></asp:TextBox>
<asp:Button runat="server" ID="Submit" Text="Submit this other form"/>
It looks like an .aspx page but it has no form. It can still have its own code behind which can interact with with the other server controls it contains, just like an .aspx page would.
Then you add that control to your "main" page:
<%# Page Language="C#" AutoEventWireup="true"
CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %>
<!-- Register the user control -->
<%# Register TagPrefix="uc" TagName="other" Src="~/OtherForm.ascx" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<!-- This form has its own stuff, but also contains the "other" form. -->
<uc:other runat="server" ID="TheOtherForm"></uc:other>
</form>
</body>
</html>
I recommend this over using panels (which still works) because if you're putting two forms on one page, it's likely that you might at some point want to move the secondary form to another page or re-use it. This approach keeps it completely self-contained. Its code-behind isn't in the same file as the the .aspx page. You can place this on as many pages as you want.
Original "literal" answer which addresses the question as originally understood.
The runat="server" form exists entirely for the purpose of allowing ASP.NET to interact with the page and its server controls during postbacks. It's central to the way webforms works. If you change the action then technically what you have isn't a webforms page any more.
That's fine (I don't even like webforms) but it can lead to some weird behavior. If you have controls that trigger postbacks then normally they'd be handled on the same page and your user would just see a (hopefully) fast refresh. Now they might get sent to another page.
What if you just removed that form entirely and added your own form instead? Then your .aspx page will just behave more like an .html page.
Having added all the disclaimers about why not to do it, you can change the action using JavaScript. Here's a sample:
<%# Page Language="C#" AutoEventWireup="true"
CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server" ClientIDMode="Static">
<asp:Button runat="server" text="Causes postback"/>
<asp:CheckBox runat="server" AutoPostBack="True"/>
</form>
<script>
document.getElementById("form1").action = "http://stackoverflow.com";
</script>
</body>
</html>
Some browsers might not allow changing the form's action.
I put the checkbox there just for fun (I must be really bored) to show the odd side effects it could have, that you might click on a checkbox and get redirected to a different page.
You can write a response.write() in your Asp.net side that print some javascript or jQuery code! As #Scott Hannen wrote some javascript like this :
Response.Write("<script>document.getElementById('YOURFORMID').action = 'YOUR URL';</script>");
or with jQuery
Response.Write("<script>$('#YOUR FORM ID').attr('action', 'YOUR URL');</script>");
btw if you have access to .html or .js files u can directly put this jQuery code without any C# code!
first let me say that even though I am 60 years of age I am relatively new to c# and definitely new to asp.net.
I was doing a simple demo that I copied from the web, where I have a very minimal web form that only has a text box and a button. The code compiles and when run the web form it comes up and shows the proper button and text box. However, when I click the button, I should get an event to happen which does not happen. In fact, when I am debugging, I see that the program never executes to the event that increments the button click count. Of course, I am clicking the button during debug mode and I never see the click increment function executed.
Evidently the event of the button click is not being executed.
I have included a picture of the simple web form (hopefully, it will come through)
Thank You
Tom
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ViewStateDemo
{
public partial class WebForm1 : System.Web.UI.Page
{
int ClicksCount = 0;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
TextBox1.Text = "0";
}
}
protected void Button1_Click(object sender, EventArgs e)
{
ClicksCount = ClicksCount + 1;
TextBox1.Text = ClicksCount.ToString();
}
}
}
Simple Web Form
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="ViewStateDemo.WebForm1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:Button ID="Button1" runat="server" Text="Button" />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</form>
</body>
</html>
You didn't wire up your event. You have to tell the button what method to call when it's clicked.
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
By the way, you're learning ASP.NET Web Forms. Web Forms future is unclear, and bleak, and it's considered by many professionals to not be that great. If you're just starting out, you should learn ASP.NET MVC.
I have a simple web page that contains a Literal, now I want to create a form tag in code behind.
This is an example:
if (IsPostBack)
{
Literal1.Text = "form submit";
}
else
{
Literal1.Text = "<form id='myFrom' runat='server' action='default.aspx'
method='POST'><input type='submit' value='click here'/></form>";
}
This code create the form, but when I click the submit button, it doesn't go through IsPostBack path. Why?
Note that I need it to be created and sent as an string, because I want to use it in ajax for example.
IsPostBack is only enabled when the POST request originates from ASP.NET's __doPostBack() function. See How to use __doPostBack() for how to create an async postback request with JavaScript.
An ASP.NET web form is already an HTML form and encompasses all of your controls. You are nesting a form within a form which is not legal HTML.
I'd suggest you replace your nested form with a simple button. In the click handler for the button, redirect to default.aspx.
As indicated by John Wu, you don't want to implement your code this way. Nested forms -- while browsers forgive them -- are just not the way to go, especially with ASP.Net WebForms. Sure, I was able to get your code to work, BUT if you need to ajaxify your page so that it works with the WebForms postback model, then it would be much better to use the UpdatePanel control (in conjunction with the ScriptManager control).
ASP.Net WebForms is predicated on only having a single Form element used on a page, as it relates to its postback model, so you'll want to work within that constraint.
Here's some code to demonstrate the use of the UpdatePanel to ajaxify a WebForm (and take advantage of PostBack):
...the .ASPX page:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="NestedForm_Question.aspx.cs" Inherits="StackOverflowAspNetQuestionAnswers.NestedForm_Question" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager" runat="server" />
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:Literal ID="Literal1" runat="server" />
<asp:Button ID="SubmitButton" Text="Submit" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
...the associated code-behind class:
public partial class NestedForm_Question : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
SubmitButton.Click += SubmitButton_Click;
}
void SubmitButton_Click(object sender, EventArgs e)
{
Literal1.Text = "form submit";
}
}
You can see that in the code-behind class, the code that would need to be written to set the value of the literal control after the Button is clicked is the same whether the page is ajaxified or not.
I've changed my code to this:
if (Context.Request.Form.HasKeys()) // instead of if(IsPostBack)
{
Literal1.Text = "isPostBack";
}
else
{
Literal1.Text = "<form id='myFrom' runat='server' action='default.aspx' method='POST'><input type='submit' name='submitbtn' value='click here'/></form>";
}
Using different examples, I didn't find any exception to this. and it works well.
Any idea about this solution?
Note that in this way at least one of our elements in the form should have the name property.
I have following Index.aspx web form:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="ProblematicWebApplication.Index" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<asp:Label ID="dummyLabel" runat="server" Text="This is dummy label." />
<form id="form1" runat="server">
<div>
<asp:DropDownList ID="intDropDownList" runat="server"/>
<br />
<asp:Button Text="Submit" OnClick="OnSubmitClicked" runat="server"/>
<br />
Selected value: <asp:Label ID="selectedValueLabel" runat="server" />
</div>
</form>
</body>
</html>
And following code behind Index.aspx.cs file:
using System;
using System.Linq;
namespace ProblematicWebApplication
{
public partial class Index : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
this.intDropDownList.DataSource = Enumerable.Range(0, 11).ToArray();
this.intDropDownList.DataBind();
}
if (this.Request["remove-dummy"] != null)
this.Controls.Remove(this.dummyLabel);
}
protected void OnSubmitClicked(object sender, EventArgs e)
{
this.selectedValueLabel.Text = this.intDropDownList.SelectedValue;
}
}
}
When I run my application with no remove-dummy parameter in query string and select some value from intDropDownList and click Submit button, selected value is accordingly presented in selectedValueLabel.
But if I run my application with remove-dummy=1 parameter in query string, dummyLabel gets removed. Now when I select some value from intDropDownList and click Submit button, selected value is not correctly written to selectedValueLabel and all items from intDropDownList are removed.
Can someone explain it to me why this is happening?
Why removing unrelated dummyLabel control has influence on intDropDownList control?
Hmm, seems odd. I got it to work by moving your code that removes the control into the Page's PreInit event:
protected void Page_PreInit(object sender, EventArgs e)
{
if (this.Request["remove-dummy"] != null)
{
this.Controls.Remove(this.dummyLabel);
}
}
It seems that ViewState loading fails in postback after dummyLabel is removed in previous page load.
Details:
first study following articles:
TRULY Understanding ViewState - Infinities Loop
ASP.NET Page Life Cycle Overview
Following image shows important ASP.NET page events and where in between ViewState handling takes place.
So what happens when declarative Control dummyLabel is removed? Here is a process:
Page is requested for the first time with query string parameter remove-dummy=1.
In Page_Load event declarative Control dummyLabel is removed.
Before SaveStateComplete event, ViewState is saved. There is no control dummyLabel in control tree, so its ViewState won't be saved.
Submit button is clicked.
Between InitComplete and PreLoad events, ViewState gets loaded. This is where it breaks because control tree now contains dummyLabel (dummyLabel gets removed after, in Load event) and ASP.NET fails in recursively loading ViewState into Page control tree. My assumption is that ViewState and Page control tree are tightly coupled and recursive ViewState loading fails as a consequence of this tight coupling.
One more situation that backs-up this theory: if you place dummyLabel at the very end of the page, issue doesn't happen anymore, because all other controls in Page control tree that come before dummyLabel already picked correct values from ViewState (ViewState structure and Page control tree are tightly coupled). If there were more controls after dummyLabel, their ViewState loading would fail.
To resolve this issue, all declarative Controls (defined in ASPX file) that should be removed, must be removed before ViewState loading takes place - in InitComplete event or any other event before it.
I would like to add a literal dynamically on a page but right after the </head> and before the <body>. How can i find this section programatically and add a literal dynamically ? So basically the page would end up looking like this:
<head>
</head>
<LITERAL HERE>
<body>
</body>
I sort of saw how to find the head tag but I do not know how to tell it to add the literal right after it closes and before the body. (This is for the Bing Ad Center tracking code as they suggest to put it there). But it needs to be dynamic because we will not always add tracking every time the user arrives to this page but only depending on certain cases.
Thank you
You can use delimiters to insert the contents of a String directly into your page.
<head runat="server">
<title></title>
</head>
<%= TrackingString %>
<body>
</body>
Make sure you have this string declared globally on the page that is referencing it, and as you manipulate this string on the page, it will be written to the page as text and parsed as HTML:
public partial class Default : System.Web.UI.Page
{
public string TrackingString;
protected void Page_Load(object sender, EventArgs e)
{
TrackingString = "<YourHtmlTag></YourHtmlTag>";
}
}
In those cases where you do not want to track the user, simply set the string to String.Empty or to "" and nothing will be written to the HTML.
You can use literal control and bind text in page load event
<head>
<asp:Literal ID="literal1" runat="server"></asp:Literal>
<title></title>
</head>
C#
protected void Page_Load(object sender, EventArgs e)
{
if(condition)
{
literal1.Text = "html or script tag";
}
}