asp.net update UI using multi-thread - asp.net

I have an ASP.NET website containing the following
<asp:UpdatePanel ID="UpdatePanel1" runat="server" >
<ContentTemplate>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
I have created a thread function. And during the execution of this function I would like to update some controls on the user interface.
protected void Page_Load(object sender, EventArgs e)
{
new Thread(new ThreadStart(Serialize_Click)).Start();
}
protected void Serialize_Click()
{
for (int i = 1; i < 10; i++)
{
Label1.Text = Convert.ToString(i);
UpdatePanel1.Update();
System.Threading.Thread.Sleep(1000);
}
}
How could I update a web-control during a thread-execution? do I need to force the "UpdatePanel1" to post-back? how?

You'll need to use a client-side timer (or some other method) to have the browser ask the server for the update, such as this simplified example:
<asp:UpdatePanel ID="up" runat="server">
<ContentTemplate>
<asp:Timer ID="Timer1" runat="server" Interval="1000" OnTick="timer_Ticked" />
<asp:Label ID="Label1" runat="server" Text="1" />
</ContentTemplate>
</asp:UpdatePanel>
Then in your codebehind:
protected void timer_Ticked(object sender, EventArgs e)
{
Label1.Text = (int.Parse(Label1.Text) + 1).ToString();
}
If you have a background process that is updating some state, you will either need to store the shared state in the session, http cache, or a database. Note that the cache can expire due to many factors, and background threads can be killed any any tie if IIS recycles the application pool.

This won't do what you think it will.
It would make more sense to use a js timer on the front end to call a webmethod that updates the page.
Remember that to the server, once the page is rendered to you, it does not exist anymore until called again. The web is a stateless medium. Postback and viewstate make it feel like it's not, but it really is.
As such, you won't be able to call the client from the server, which is what you are attempting to do.

You would have to use javascript/jquery to poll the server for changes. This is one of the more unfortunate side-effects of all this fancy-schmancy jquery/ajax stuff: people forget that the browser must poll the web server - it's a one way connection only, even if it does sometimes feel like a client winforms app. Ultimately, the browser must make a http post/get request of its own accord. Yes, you can emit client javascript ahead of time to tell it to do so, but this requires that you know when exactly to call back. It sounds like you have some arbitrary code that will be done when it's done, so in this case you must continually poll.
-Oisin

Related

private static variable is replace with latest value when accessing from different browser - c#

My web page is showing the details of selected student(using the studentid) in a gridview. I have put an updatepanel with timer for this gridview to auto refresh the data within an interval of time. But now the issue is when a user1 is seeing the details of student1 from his system. and another user2 is seeing the details of student2 from his system. when the timer executes the updatepanel , both the user is seeing the latest student (student2) details.
In short, when same web page is used by multiple users at same time, it shows the student details of latest user selected.
I have set the student id as private static. Will it be individual for each browser? Or will it be the issue of updatepanel with timer?
<asp:UpdatePanel runat="server" ID="UpdatePanel1" UpdateMode="Conditional">
<ContentTemplate>
<asp:Timer ID="Timer2" runat="server" Interval= "<%$appSettings:update_timer%>" OnTick="Timer1_Tick"></asp:Timer>
<asp:GridView ID="gv_studentdetails" runat="server" AutoGenerateColumns="true" Caption="Student Details"
CssClass="gridview_alter" >
</asp:GridView>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Timer2" EventName="Tick" />
</Triggers>
</asp:UpdatePanel>
In web.config file
<add key="update_timer" value="30000"/>
Code behind:
private static int student_id;
if (!IsPostBack)
{
student_id=Convert.ToInt32(Session["selected_studentID"]);
BindGridview(student_id);
}
protected async void Timer1_Tick(object sender, EventArgs e)
{
BindGridview(student_id);
UpdatePanel1A.Update();
}
NB: This issue is happening when run the timer of updatepanel only. When manually reload the page it is not .
private static int student_id;
The value will be the same within a single web-server. No matter the browser sessions. That is why both browsers start to see the last value for the server.
But whenever someone reloads the page it will set the private field to their won session's selected_studentID. So then all the browsers will get that value evenutally.
if (!IsPostBack)
{
student_id=Convert.ToInt32(Session["selected_studentID"]);
BindGridview(student_id);
}
Note:
Manipulating a static instance without lock, may cause an issue. You can read more here c# critical sections, lock

showing the loop value in label runtime ASP..NET

Iam newbie to ASP.NET, and this is my first question on this forum.
Here is my code:
protected void Button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
Label2.Text = i.ToString();
UpdatePanel1.Update();
Thread.Sleep(3000);
}
}
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click"/>
<asp:Label ID="Label2" runat="server" Text=""></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
I want to display the value of i each time when its get updated, but I got the value 9.
Please help me how can achieve my goal... No luck so far
You can't update the page in the browser directly from server code. Any updates to the page are sent back to the page when the server code ends.
The Update method only tells the update panel that it should be included in the data that is sent back to the browser when the page is complete, it doesn't send the update directly to the browser.
To periodically update content in the browser using server code you have to control it from the browser, and the server code should just do one update and then exit so that the update is sent back to the browser. You can user a timer control that will make requests to the server for every tick, or you could use Javascript code to request data from a server page.

asp.net based chat - where to go from here?

I'm building a very simple chat page on my website, here is what I have so far:
And this is the code:
<asp:Content ID="Content2" ContentPlaceHolderID="maincontent" Runat="Server">
<script language="javascript" type="text/javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(EndRequestHandler);
function EndRequestHandler(sender, args) {
document.getElementById('<%=FormView1.FindControl("chattxt").ClientID%>').focus();
}
</script>
<div id="chatbg">
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<div id="chatmessages">
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1">
<ItemTemplate>
<asp:Literal ID="Literal1" runat="server" Text='<%# Eval("Username") %>'></asp:Literal>: <asp:Literal ID="Literal2" runat="server" Text='<%# Eval("Message") %>'></asp:Literal><br />
</ItemTemplate>
</asp:Repeater>
</div>
<asp:ListBox ID="ListBox1" runat="server" Rows="16" CssClass="memberlist"></asp:ListBox>
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:FormView ID="FormView1" runat="server" DefaultMode="Insert"
OnItemInserted="fv_ItemInserted" RenderOuterTable="False"
DataSourceID="SqlDataSource1">
<InsertItemTemplate>
<asp:Panel ID="Panel1" runat="server" DefaultButton="Button1">
<asp:TextBox ID="chattxt" runat="server" CssClass="chattxtbox"
Text='<%# Bind("Message") %>' autocomplete="off"></asp:TextBox>
<asp:Button ID="Button1" runat="server" CommandName="insert" style="display:none" Text="Button"/>
</asp:Panel>
</InsertItemTemplate>
</asp:FormView>
</ContentTemplate>
</asp:UpdatePanel>
</div>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:orangefreshConnectionString1 %>"
InsertCommand="INSERT INTO [Chat] ([Username], [Message]) VALUES (#Username, #Message)"
SelectCommand="SELECT [Id], [Username], [Message], [Date] FROM [Chat] ORDER BY [Id]" >
<InsertParameters>
<asp:Parameter Name="Message" Type="String" />
<asp:Parameter Name="Date" Type="DateTime" />
<asp:SessionParameter Name="Username" SessionField="Username" Type="String" />
</InsertParameters>
</asp:SqlDataSource>
<script type="text/javascript">
function scrollpos() {
var objDiv = document.getElementById("chatmessages");
objDiv.scrollTop = objDiv.scrollHeight;
}
</script>
</asp:Content>
The script at the top of the page puts the focus back on my Textbox
after a postback.
The script at the bottom of the page makes sure the scroll on the message window is always at the bottom through post backs.
This is my codebehind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Security;
using orangefreshModel;
public partial class chat : BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
Session["Username"] = User.Identity.Name;
ListBox1.Items.Clear();
foreach (MembershipUser myuser in Membership.GetAllUsers())
if (myuser.IsOnline == true)
{
ListBox1.Items.Add(myuser.ToString());
}
ScriptManager.RegisterStartupScript(
UpdatePanel1,
this.GetType(),
"ScrollPos",
"scrollpos();",
true);
}
protected void fv_ItemInserted(object sender, FormViewInsertedEventArgs e)
{
this.FormView1.DataBind();
}
}
So all of this is working pretty good, the UpdatePanel ensures my messages popup straight away, the problem now is seeing other user messages. This is my first ever ASP.NET project, so I thought about cheesing it a bit and trying a Timer every second to repopulate my repeater... but to no success, and I don't think it's a wise solution at all:
First of all, the Timer affecting my Repeater window made it impossible for a user to scroll back up to read messages, seeing as it refreshed every second scrolling was just not possible.
Secondly, I never got it to work anyway, this is the event I tried for my Timer:
protected void Timer1_Tick(object sender, EventArgs e)
{
this.Repeater1.DataSource = SqlDataSource1;
this.Repeater1.DataBind();
}
But yeah, no success.
This is where I'm at right now with this chat: I can see my messages popping up fine, but now I need to figure out a way for my window to update as other users type their message, if some other user types a new message in, I need to send in my own message in order to see theirs.
I've been browsing the web for a bit, read a few things about Signal R, but I was wondering if someone had simpler idea on where I should go with this, how to implement real time updates on my message window?
I suggest looking into SignalR - http://nuget.org/packages/signalr
SignalR is a library that keeps persistent connection open and allows the server to "push" data to the client.
You can also look at http://www.slideshare.net/adammokan/introduction-to-signalr-10082193 as a decent overview of SignalR
It
One option is to do this outside of the ASP.Net lifecycle and makea manual AJAX request to the server. The server method can hold on to the connection for a max of 30 secs, returning any new messages as soon as they arrive. This is then returned to the client and handled in JS, and they then open another connection and wait again. I've heard this called the reverse AJAX poll.
However you detect new messages is up to you, you could poll the DB every second, or maintain in memory message etc.
Note that this can cause problems if thousands of clients are holding open connections to the server.
I agree with KingPancake that SignalR would be a very good way to approach something like this. You could "back-end" this with something like the new .Net Web API in conjunction with SignalR if you want to persist the data at all
Check out this presentation by Brad Wilson which might help you:
SignalR is a good option.
However if you do want to do it yourself for some reason, this is how you should go about it.
The most efficient method to build a chat in asp.net is to use a IHttpAsyncHandler and ajax requests.
An async request allows you to delay the response of a request till an external event occurs.
A user makes a call to this handler and waits till someone sends him a message.
Messages are delivered as soon as you send them to a user.
On receiving a message the client makes another request and waits for the next message.
This is how you keep a persistent connection open and allows the server to push data to the client.
This is a lot more efficient than polling the site to check if messages have arrived.
Using the async handler also ensures that no asp.net threads are wasted while a user waits for messages to come. Polling with a timer you will quickly run out of threads to process requests in asp.net.
This ensures that your chat can scale well even as the number of users of the site goes up.
Here is a completely working project that implements this, along with ajax.

parralel ASP.NET Timer Controls

I have a problem and I'd really appreciate a little help.
On my .aspx I have four ASP.NET Timer Controls and when each of them Ticks I call asynchronously different web service method that returns me some photos. I have a image in Update Panel and update it src when I get a photo. I'm using a jQuery lightBox plugin to preview a image.
The problem is that: I would like the Timers work in the same time (simultaneously). So on page Load, after some seconds should appear a Tick of each Timers (parallel, more less in the same time). Both Timers have the same time Interval so it should work, but in practice I've noticed that the second Timer ticks only after the first web service callback appears, and the third Timer ticks after the second web service callback appears. So it all works linearly, not parallel.
Any solutions how to modify it to Tick simultaneously ?
my .aspx:
<center>
<asp:Timer runat="server" ID="UpdateTimer1" OnTick="UpdateTimer1_Tick" />
<asp:UpdatePanel runat="server" ID="TimedPanel2" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="UpdateTimer1" EventName="Tick" />
</Triggers>
<ContentTemplate>
<asp:Literal runat="server" ID="Ltr1" />
<div id="div1" runat="server">
<img alt="" id="img1" runat="server" style="width: 85%; height: 85%" />
</div>
</ContentTemplate>
</asp:UpdatePanel>
</center>
one of my Timers in .aspx.cs, the rest of Timers is similar - the call different webservice, but have the same events, updateTimer_Ticks etc:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
UpdateTimer1.Interval = 3000;
{
}
protected void UpdateTimer1_Tick(object sender, EventArgs e)
{
AsynchGetPhoto();
}
public void AsynchGetPhoto()
{
WS.Service Service = new WS.Service();
Service.getPhotoCompleted += new Service.getPhotoCompletedEventHandler(PhotoCompleted);
Service.getPhotoAsync();
}
public void PhotoCompleted(object sender, WS.Service.getPhotoCompletedEventArgs args)
{
img1.Attributes.Add("src", "data:image/jpg;base64," + args.Result);
}
What i can tell you about your problem is my understanding about how this timer is working and happens behind the scene and you can investigate more in your code.
When the timers tick an asynchronous request to your function is done so each timer shall fire it's own request and the browser shall handle all the requests in parallel so i suggest that you open the firebug and see your timers requests and see if they are depending on each other and each request is handled after the other or it is just the rendering mechanism of the browser causing the timers to delay.

ASP.Net: Ajax check for registration as a user?

I have an user registration on my site.
I want to look it cool, so my plan is, that after a textbox is left, a green or red sign right behind the textbox tell the user if e.g. the username is unused, the email-adress is unused, the password is correct entered twice and so on.
Yes, I know the validation controls, but there are only a bunch of functions, isn't it? E.g. for checking if the email-adress is unused I must check by database and so on...
Any Ideas?
I would wrap the whole thing in an update panel, this is something I do quite often...
<asp:scriptmanager runat="server" id="sm1" />
<asp:updatepanel runat="server" id="up1" updatemode="Conditional">
<contenttemplate>
<asp:textbox runat="server" id="tbUsername" autopostback="true" ontextchanged="tbUsername_TextChanged" />
<asp:customvalidator runat="server" text="Email already used" id="cusValEmail" />
<asp:textbox runat="server" id="tbPassword" />
</contenttemplate>
</asp:updatepanel>
and in the code behind
protected void tbUsername_TextChanged(object sender, EventArgs e)
{
//call DB etc and mark validator as needed
cusValEmail.IsValid = false;
}
The key is setting the textbox autopostback to true and utilising the ontextchanged event.
A simple way of doing this would be to create a controller action (if you are using MVC) or a page (if you are using regular asp/asp.net) that you post the username, e-mail address, etc to that returns a simple plain-text colour value - red or green, depending on whether all the parameters have been posted are ok. You could then apply that to the colour-style of the box. If you don't have/want that to be an https call then I probably wouldn't include the passwords in that, you ajax return code could maybe say
if (<password are equal>)
{
set style-colour to the return value
}
else
{
set to red
}
or probably, even better, something like
if (<passwords are equal>)
{
run ajax call
}
else
{
set style-colour to red
}
and the the ajax return sets the colour to the return value, that way you also save a round trip to the server if the passwords aren't equal
Any reason you want/need to do this via ajax rather than a regular postback (you could use an update panel to do a partial postback)?

Resources