Easy wait script - c#

I'm trying to implement in my web form an easy wait function, it works, but not as I would.
My code is this:
for(int i = 0; i<5; i++)
{
Label1.Text = "Invio: " +i;
System.Threading.Thread.Sleep(6000);
}
The problem is that Label Text doesnt' change every 6 seconds.
This script should use 30second and change the label text in this manner:
"Invio: i" every 6 seconds.
Instead it waits 6 seconds and then it change the text in "Invio 4".
Why?

The reason this happens is because of the view state . Before you render your page the back-end code is executed, after it finishes, the DOM start to render and then your page is ready. That means your page won't refresh the label value every N seconds, because it has been already set. If you want to change the value of this dynamically you should use some front-end method as JavaScript or jQuery. If you want this approach - comment so I can make a fiddle for you.
Also this would be helpful for you - ViewState
Here is a fiddle to check if you want something like this - Fiddle demo
var count = 1;
time = setInterval(function(){
document.getElementById("label1").innerHTML="Indio: " + count;
count+= 1;
if (count == 5)
{
clearInterval(time);
}
},6000);

Back end like this:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Timer1_Tick(object sender, EventArgs e)
{
Label txt = Label1;
int i = Convert.ToInt32(txt.Text);
if (i == 4)
{
Timer1.Enabled = false;
}
else
{
i++;
Label1.Text = i.ToString();
}
}
}
and front-end is like this:
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Timer ID="Timer1" runat="server" OnTick="Timer1_Tick" Enabled="true" Interval="6000">
</asp:Timer>
<asp:Label ID="Label2" runat="server" Text="Invio: "></asp:Label>
<asp:Label ID="Label1" runat="server" Text="0"></asp:Label>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Timer1" />
</Triggers>
</asp:UpdatePanel>
</asp:Content>
This will loop 5 times with a 6 second interval.
Timer on page will trigger a postback, server side will execute and will update an updatepanel.

Unfortunately there is no easy way of doing that kind of thing purely using basic Asp.Net webforms (unless you use Asp.Net Webforms AJAX - which I personally find very confusing).
Assuming you are trying to provide some feed back to your user, about a long running operation, I'd use a combination of javascript (using JQuery Ajax for example) and a simple page to poll if the task is done, then redirect to result page.

Related

ASP.NET: Update ListView from CodeBehind

So there's a ListView element on my ASP.NET page that I need to be able to update from the code behind. To my understanding, Microsoft has prepared UpdatePanels and DataBindung for exactly such purpose, allowing me to "bind" the ListView's content to a property member in the code behind and promising to take care of updating the browser's view automatically (?) when the property changes.
However, only the initial load of items via GetStuff() works; I can see in the debug console that my timer keeps adding new elements to the List, but those never arrive in the browser's view. What am I missing?
In Default.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="myLittleProject.Default" %>
<%# Register Src="~/StuffListItemControl.ascx" TagPrefix="stf" TagName="StuffListItem" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<!-- some irrelevant stuff -->
</head>
<bod>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager" runat="server"></asp:ScriptManager>
<!-- some irrelevant stuff -->
<asp:UpdatePanel runat="server" ID="StuffUpdatePanel" UpdateMode="Always">
<ContentTemplate>
<ul>
<asp:ListView ID="StuffBoundContent" runat="server">
<ItemTemplate>
<stf:StuffListItem runat="server" ID="StuffListItemControl" />
</ItemTemplate>
</asp:ListView>
</ul>
</ContentTemplate>
</asp:UpdatePanel>
<!-- some more irrelevant stuff -->
</form>
</body>
</html>
And in Default.aspx.cs:
using System.Collections.Generic;
namespace myLittleProject
{
public partial class Default : System.Web.UI.Page
{
public static List<Stuff> StuffContent;
protected void Page_Load(object sender, EventArgs e)
{
StuffContent = Stuff.GetStuff(); // returns a list of three elements from the database
System.Timers.Timer t = new System.Timers.Timer();
t.Interval = 3000;
t.Elapsed += T_Tick;
t.Enabled = true;
}
protected void Page_PreRender(object sender, EventArgs e)
{
StuffBoundContent.DataSource = StuffContent;
StuffBoundContent.DataBind();
}
private void T_Tick(object sender, EventArgs e)
{
StuffContent.Add(new Stuff(StuffContent.Count + 1, DateTime.Now.ToShortDateString(), new string[] { "what", "ever" }));
System.Diagnostics.Debug.WriteLine("[TIMER EVENT] StuffContent.Count = " + StuffContent.Count.ToString());
}
}
}
System.Timers.Timer does not work with a webpage. The reason that t is disposed after the page is sent to the client. Use a Timer control if you really want to use one.
<asp:Timer ID="Timer1" runat="server" OnTick="Timer1_Tick"></asp:Timer>
And then you can update the ListView in Timer1_Tick.
protected void Timer1_Tick(object sender, EventArgs e)
{
//update the ListView
}
Place the Timer Control inside the UPdatePanel if you do not want a full postback when the timer is triggered.
Another thing to remember is that although you use an UpdatePanel, a complete page life cycle is triggered. So all other code you use in Page Load (and PrerRender) is executed even when only the ListView update is visible to the user. This could put a huge load on the server when an updatepanel is triggered every few seconds. Maybe better use Ajax.
PS you don't need to use Page_PreRender to bind data.

Update panel to display output from console

I'm trying to show the console output from a process started by my webapp. I tried to set it up so that when I receive a line of text, I update the label then reload (update) the update panel, but the panel doesn't seem to update.
I can't figure out why my update panel isn't updating. I print out the console output as it is received, but the update panel doesn't update at all.
protected void RunBatch_Click(object sender, EventArgs e)
{
Process p = new Process();
p.StartInfo.FileName = #"C:\...\test.bat";
// Set UseShellExecute to false for redirection.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
// Set our event handler to asynchronously read the sort output.
p.OutputDataReceived += new DataReceivedEventHandler(OutputReceived);
// Start the process.
p.Start();
// Start the asynchronous read of the sort output stream.
p.BeginOutputReadLine();
}
protected void OutputReceived(object sender, DataReceivedEventArgs e)
{
Output_lbl.Text += e.Data;
System.Diagnostics.Debug.WriteLine(Output_lbl.Text); // I see this output
UpdatePanel1.Update(); // Doesn't update
}
.
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="Testing._Default" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<p>
<asp:Button ID="RunBatch" runat="server" Text="Run Batch!"
onclick="RunBatch_Click" />
</p>
<asp:ScriptManager runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" >
<ContentTemplate>
<asp:Label ID="Output_lbl" runat="server" Text="Label"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
</asp:Content>
.
EDIT:
I changed the Update Panel's UpdateMode.
I've tried to implement a timer to update the update panel, which it does, but it prints out "1:48:07 PM -- " ... and continues to count without printing any other Text even after receiving the debug messages:
This is the output from the batch file
This is the output from the batch fileThis is output line 2 from the batch file
This is the output from the batch fileThis is output line 2 from the batch fileThis is output line 3 from the batch file
.
string Text = "";
protected void OutputReceived(object sender, DataReceivedEventArgs e)
{
Text += e.Data;
System.Diagnostics.Debug.WriteLine(Text);
}
protected void Timer1_Tick(object sender, EventArgs e)
{
Output_lbl.Text = DateTime.Now.ToLongTimeString() + " -- " + Text;
}
Your panel doesn't update because you set the UpdateMode to Conditional without specifying any triggers that would cause it to postback to the server asynchronously and fetch the updated content. You would need to embed a Timer in the UpdatePanel and configure that as a trigger for the UpdatePanel. See article How to refresh update panel with a timer.
Instead of using an update panel, why don't you try using AJAX combined with a web method? UpdatePanels are notoriously difficult to work with.
Edit...
I think you're missing the idea that each request to the webserver is unique, so you need a way to persist the output from the console program between postbacks. Below, I make use of Session.
Code behind
protected void Timer1_Tick(object sender, EventArgs e)
{
Output_lbl.Text+=Session["Text"].ToString();
}
protected void OutputReceived(object sender, DataReceivedEventArgs e)
{
Session["Text"]+=e.Data;
System.Diagnostics.Debug.WriteLine(Text);
}
The ASPX page.
<asp:UpdatePanel runat="server" ID="UpdatePanel1" UpdateMode="Conditional" ChildrenAsTriggers="false">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
</Triggers>
<ContentTemplate>
<asp:Timer runat="server" ID="Timer1" OnTick="Timer1_Tick" Interval="150" />
<asp:Label ID="Output_lbl" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>

How to create asp.net app combining ListBox, TextBox and Button

I'm designing small instant messenger app on .NET platform.
I have a ListBox, TextBox and Button (called Send).
When user click send button, Text of TextBox will be appeared on ListBox but user should not send 3 messages in 1 minute(message restriction) and also his/her size of message should consist min 20 max 140 strings.
How can I do this?
The example below uses the timer control, if you would like to learn more about using timers in ASP.NET have a look at this video tutorial by Joe Stagner.
Basically I'm storing the number of messages in ViewState and when that number reaches 3 I start the timer which will reset the ViewState["Messages"] back to 0 after 1 minute (60 000 milliseconds) and the user is once again able to send more messages.
ASPX:
<asp:ScriptManager ID="Scriptmanager" runat="server" />
<asp:Timer ID="timer" runat="server" Enabled="false" Interval="60000" OnTick="Tick" />
<asp:UpdatePanel ID="updatePanel" runat="server">
<ContentTemplate>
<asp:TextBox MaxLength="140" ID="txtMessage" runat="server" />
<asp:Button ID="btnSend" runat="server" Text="Send" OnClick="Send" /> <span
id="error" runat="server" style="color: Red;" />
<br />
<asp:ListBox ID="lbMessages" runat="server" Width="240" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="timer" />
</Triggers>
</asp:UpdatePanel>
Code behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
ViewState["Messages"] = 0;
}
public void Send(object sender, EventArgs e)
{
error.InnerHtml = string.Empty;
string message = txtMessage.Text;
if (message.Length < 20)
{
error.InnerHtml = "The message should be at least 20 characters long";
return;
}
int messageNumber = (int)ViewState["Messages"];
if (messageNumber < 3)
{
lbMessages.Items.Add(message);
ViewState["Messages"] = ++messageNumber;
if (messageNumber.Equals(3))
timer.Enabled = true;
}
}
protected void Tick(object sender, EventArgs e)
{
ViewState["Messages"] = 0;
timer.Enabled = false;
}
Also you don't need to check for maximum length in code, there is a property for that on the textbox - MaxLength
Maybe you can set an hidden field in your page load to store serialised three last requests time and another for last minute message count.
in the click button event get text of the textbox apply your size restriction and verify message count.

Ajax and simple button Event handlers not working

I am running into a problem with Ajax and C# asp.net. I am using Microsoft Visual Studio 2010.
First let me explain my web page.
I have script manager, and directly underneath that I have a update panel.
This is the dynamic placeholder I've been fiddling with.
http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx
Within my update panel, I have a dynamic control & a button.
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<asp:ScriptManager ID="ScriptManager1" runat="server" >
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<DBWC:DynamicControlsPlaceholder ID="DynamicControlsPlaceholder1"
runat="server">
</DBWC:DynamicControlsPlaceholder>
<br />
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
</asp:Content>
Now in my code behind:
I simply add 5 text boxes to a dynamic control. Page load;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
ViewState["id"] = 0;
int id = (int)ViewState["id"];
for (int i = 0; i < 5; i++)
{
id++;
TextBox txt = new TextBox();
txt.ID = id.ToString();
DynamicControlsPlaceholder1.Controls.Add(txt);
txt.Text = i.ToString();
}
ViewState["id"] = id;
}
}
Now all my button does is add another TextBox to the dynamic control pannel.
protected void Button1_Click(object sender, EventArgs e)
{
int id = (int)ViewState["id"];
TextBox txt = new TextBox();
txt.ID = id.ToString();
DynamicControlsPlaceholder1.Controls.Add(txt);
// DynamicControlsPlaceholder1.DataBind();
txt.Text = id.ToString();
id++;
ViewState["id"] = id;
}
* Note I am using a custom dynamic control panel so their ID's are saved to the next page even though we have them creeated in a !Page.IsPostBack
The problem is that my button event handler only works once. I'm pretty sure its because the Ajax is calling a partial postback and it's not recognizing it to call my button event handler.
I'm not sure, any help is appriciated.
Firebug works wonders for debugging ajax. "There were multiple controls with the same ID '5'."
What a simple fix. Moved id++; to the top of Button1_Click event handler.
If you're ever assuming ajax is breaking your event handler just because the breakpoint is not firing in the event handler, firebug may save you too!
There was absolutely nothing wrong with the event handler, but the code within it was causing an error and ajax wasn't allowing it to break.

AsyncFileUpload postback causes double upload

I implemented the AsyncFileUpload control on a web page. This web page requires uploaded files to appear in a GridView.
The GridView contains the following columns: "File Name", "Confidential" Check Box, and a "Remove" button to remove the uploaded file.
Since the AsyncFileUpload postback does not do a full page postback, I need to "force" a postback on the OnClientUploadComplete event of the AsyncFileUpload control in order to render the gridview after uploading a file.
In the OnClientUploadCompleteEvent, I use javascript to call __doPostBack. In this postback, I only bind my GridView and display the file information (I don’t re-save the file).
The problem: On the AsyncFileUpload’s first “partial” postback, the file is successfully uploaded, as expected. On the second postback that I force with __doPostBack, the file is re-uploaded.
You can verify this by using Google Chrome, which displays the upload progress. The behaviour is as follows:
- After selecting the file, the progress increments from 0% to 100% and the file is uploaded.
- After this, the __doPostBack executes, and you can see the upload progress increment again from 0% to 100%.
How can I make sure the Gridview is properly populated, but that the file is not uploaded twice?
I attached a sample solution which contains the issue: https://www.yousendit.com/download/MzZFc2ZBNDRrYUN4dnc9PQ
There is a simpler solution
##t0x1n3Himself the solution u gave is very simple but does not work
surround the AsyncFileUpload with an update panel name it UpdatePanelAFU
then in the UpdatePanelAFU do as the following :
protected void AsyncFileUpload_UpdatePanelAFU(object sender,AjaxControlToolkit.AsyncFileUploadEventArgs e)
{
if (Request.Params.Get("__EVENTTARGET") != "UpdatePanelAFU")
return;
..... rest of the code
}
enjoy!
Maybe ugly, but works:
1)
Add a css-hidden asp:Button bellow the asp:AsyncFileUpload AsyncFileUpload1 control.
<asp:Button runat="server" ID="btnClick" Text="Update grid" style="display:none"/>
2)
On the Page_Load method, remove the if (Request.Params.Get("__EVENTTARGET") == "UploadPostback") and put its block in a simple else to the previous if.
3)
On the AsyncFileUpload1_UploadedComplete function, also remove the if (Request.Params.Get("__EVENTTARGET") != "UploadPostback") line, but leave intact everything that was inside it.
4)
Back to the aspx. Put a asp:UpdatePanel outside the grid GridView1.
<asp:UpdatePanel runat="server" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnClick" EventName="Click" />
</Triggers>
<ContentTemplate>
<asp:GridView ID="GridView1" ...
YOUR GRID CODE REMAINS THE SAME
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
5)
The last step is to change the AjaxUploadComplete client-side javascript function to make it trigger the postback.
Replace it with the following:
function AjaxUploadComplete() {
var btnClick = document.getElementById("btnClick");
btnClick.click();
}
Any file the user selects is uploaded only once.
All changes here are meant to be made in AjaxUpload.aspx & AjaxUpload.aspx.cs of your AjaxUpload.zip.
I believe #Veera had it right. UploadComplete was being called multiple times as the file was uploading. The following worked for me.
void AsyncFileUpload1_UploadedComplete(object sender, AsyncFileUploadEventArgs e) {
if (AsyncFileUpload1.IsUploading) return;
// rest of your upload code
}
I don't have access to your sample solution which contains the issue but i encounter a double postback too in my project with the AsyncFileUpload component.
I found a very simple workaround :
Just add:
private bool justUploaded = false;
Then:
void AsyncFileUpload1_UploadedComplete(object sender, AsyncFileUploadEventArgs e)
{
if (justUploaded) return;
justUploaded = true;
// rest of your upload code
}
I find this a more elegant solution, found here: http://forums.asp.net/t/1951566.aspx?AsyncFileUpload+uploads+twice) but below is my altered fully working code:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>AsyncFileUpload Example</title>
<script type = "text/javascript">
function uploadComplete(sender) {
$get("<%=lblMesg.ClientID%>").innerHTML = "File Uploaded Successfully";
clearContents();
}
function uploadError(sender) {
$get("<%=lblMesg.ClientID%>").innerHTML = "File upload failed.";
clearContents();
}
function clearContents() {
var span = $get("<%=AsyncFileUpload1.ClientID%>");
var txts = span.getElementsByTagName("input");
for (var i = 0; i < txts.length; i++) {
if (txts[i].type == "text") {
txts[i].value = "";
}
if (txts[i].type == "file") {
txts[i].value = "";
}
}
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<cc1:AsyncFileUpload OnClientUploadError="uploadError"
OnClientUploadComplete="uploadComplete" runat="server"
ID="AsyncFileUpload1" Width="400px" UploaderStyle="Modern" EnableViewState = "false"
UploadingBackColor="#CCFFFF" ThrobberID="imgLoader" OnUploadedComplete = "FileUploadComplete"
/>
<asp:Image ID="imgLoader" runat="server" ImageUrl = "~/images/loader.gif" />
<br />
<asp:Label ID="lblMesg" runat="server" Text=""></asp:Label>
</form>
</body>
</html>
AsyncFileUpload has a property that named IsUploading.
when this property is set to false, a postback will happen.
you can check this property like this:
if(AsyncFileUpload1.IsUploading)
{
..... upload codes
}

Categories

Resources