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.
Related
So the problem here is that i am unable to call a button that another developer created and handed over the site to me.
He is not available and I am not very much into ASP.net but really need to figure this out.
The code is:
<div class="clearfix">
<asp:UpdatePanel runat="server" id="UpdatePanel2">
<ContentTemplate>
<asp:Label ID="lblDesc" runat="server" Text=""/>
<asp:LinkButton ID="btnMore" runat="server" Text="more"/>
</ContentTemplate>
</asp:UpdatePanel>
</div>
The btnMore should call a button at server making the word more to be a link that will expand the div to get a blog post from the database.
It is not doing so.
Any idea why??
Your LinkButton has no associated action with it. You need to set the OnClick attribute to the function on the server side that has the correct signature. For example...
<asp:LinkButton ID="btnMore" runat="server" Text="more" OnClick="btnMore_Click" />
Then in your code behind...
protected void btnMore_Click(object sender, EventArgs e)
{
//do your server side stuff
}
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.
im trying to build a form+attachment that needs to be send to email.
Im using a VB background code (attachementemail.aspx.vb)
and my front (b-16.aspx)
I want the page to check that the user entered a email, name, phonenumber and attachment.
what command do I put in the axp.vb
and what on the .aspx
tried just about anything.
The simplest way is to use validators eg RequiredFieldValidator for mandatory fields. You can also implement CustomValidators for custom logic.
See http://msdn.microsoft.com/en-us/e5a8xz39.aspx for the available validators
At it's basic level you could use RequiredFieldValidator and CustomValidation in your form. You can use some regex logic for email, I use this but there are many out there:
Regex(#"\w+([-+.]\w+)#\w+([-.]\w+).\w+([-.]\w+)*")
Personally I use client side javascript before it hits the server and then I re-validate the entries once it hits the server. If your using the postback events then you'll need update panels and a scriptmanager (not sure if you are aware of this already, so apologies if teaching you to suck eggs!).
Here is an example:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
ErrorMessage="RequiredFieldValidator" ControlToValidate="TextBox1"></asp:RequiredFieldValidator>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
Code behind (sorry this is in c#)
protected void Button1_Click(object sender, EventArgs e)
{
if (RequiredFieldValidator1.IsValid)
{
Label1.Text = "Has content";
}
else
{
Label1.Text = "Not valid";
}
}
Note that the required field validator has it's own methods to display a "hey you haven't entered content here my friend" message, but i have added that to the label instead.
i am not sure if my design have flaw but would like to know what others have to say, i am in a situation where i am trying to acheive two things in one click.
using : asp.net web form
i have a web form with few textbox and a gridview control and a button.
if i click on the button i am executing two things
1) asynchronously get data from server to client (working great) and able to display the data in the textboxes.
2) same click i want to bind the gridview.
<asp:Content ID="Content2" ContentPlaceHolderID="cphMaster" runat="server">
<asp:Label runat="server" ID='Label1' >Id:</asp:Label>
<asp:TextBox ID="txtId" runat='server'></asp:TextBox>
<asp:Button ID="btnSubmit" OnClientClick="LoadDataById();" runat="server" Text="Submit"
onclick="btnSubmit_Click" />
<br />
<br />
<asp:TextBox ID="txtName" runat='server'></asp:TextBox> <br />
<asp:TextBox ID="txtPurpose" runat='server'></asp:TextBox> <br />
<br />
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
</asp:Content>
server side
protected void btnSubmit_Click(object sender, EventArgs e)
{
GridView1.DataSource = laodData(int.Parse(txtId.Text));
GridView1.DataBind();
}
Jquery:
function LoadVisitBasicByVisitId() {
ContactServiceProxy.invoke({ serviceMethod: "GetDataById",
data: { request: request },
callback: function(response) {
processCompletedContactStore(response);
},
error: function(xhr, errorMsg, thrown) {
postErrorAndUnBlockUI(xhr, errorMsg, thrown);
}
});
return false;
}
recap:
1) jquery script execute asynchronously to get data from server to client and display in the textboxes
2) server side code to bind the gridview.
PROBLEM:
if i have onClientClick="return LoadDataById(); then it executes ONLY ajax code and does not execute server side
but if have onClientClick="LoadDataById(); then it executes client and server but textbox value wipeout. (the textbox value popuplate through ajax)
if your jquery function would return true, your server side code would process. Returning false prevents the page from posting back to the server.
also, set your onClientClick="return LoadDataById();"
I've developed something in past with this way of think and as I remember, I have no troubles with this.
But if you return false in jQuery, postback will not happen.
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