基于asp.net的聊天 - 从哪里开始?

时间:2012-08-30 15:33:19

标签: asp.net .net

我在我的网站上建立了一个非常简单的聊天页面,这是我到目前为止所拥有的:

chat

这是代码:

<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>
  • 页面顶部的脚本将焦点放回我的文本框 在回发后。
  • 页面底部的脚本确保消息窗口上的滚动始终位于帖子的底部。

这是我的代码隐藏:

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();
    }
}

所以这一切都运行得很好,UpdatePanel确保我的消息立即弹出,现在的问题是看到其他用户消息。这是我的第一个ASP.NET项目,所以我考虑过稍微讨厌它,每隔一秒尝试一次Timer来重新填充我的中继器......但是没有成功,我认为它不是明智的解决方案:

首先,影响我的Repeater窗口的Timer使得用户无法向上滚动以阅读消息,因为每次滚动时刷新都是不可能的。

其次,我从来没有让它工作,这是我为我的计时器尝试的事件:

 protected void Timer1_Tick(object sender, EventArgs e)
        {
            this.Repeater1.DataSource = SqlDataSource1;
            this.Repeater1.DataBind();
        }

但是,没有成功。

这就是我现在正在聊聊的地方:我可以看到我的消息弹出正常,但现在我需要找到一种方法让我的窗口更新,因为其他用户输入他们的消息,如果有的话其他用户输入新消息,我需要发送自己的消息才能看到他们的消息。

我一直在浏览网页,阅读了一些关于Signal R的内容,但我想知道是否有人对我应该去哪里有更简单的想法,如何在我的消息上实现实时更新窗口?

4 个答案:

答案 0 :(得分:2)

我建议调查SignalR - http://nuget.org/packages/signalr

SignalR是一个保持持久连接打开的库,允许服务器将数据“推送”到客户端。

您还可以将http://www.slideshare.net/adammokan/introduction-to-signalr-10082193视为SignalR的理想概述

答案 1 :(得分:1)

一种选择是在ASP.Net生命周期之外执行此操作,并向服务器发出手动AJAX请求。服务器方法可以保持连接最多30秒,一旦到达就返回任何新消息。然后将其返回给客户端并在JS中处理,然后他们打开另一个连接并再次等待。我听说这叫做reverse AJAX poll

但是,您检测到新消息取决于您,您可以每秒轮询数据库,或维护内存消息等。

请注意,如果数千个客户端保持与服务器的开放连接,则可能会出现问题。

答案 2 :(得分:1)

我同意KingPancake的意见,SignalR将是一个非常好的方法来接近这样的事情。如果您希望保留数据,可以使用新的.Net Web API和SignalR“后端”这样做

查看Brad Wilson的this presentation,这可能会对您有所帮助:

答案 3 :(得分:1)

SignalR是个不错的选择。

但是,如果您确实想出于某种原因自己动手,那么就应该采用这种方式。

在asp.net中构建聊天的最有效方法是使用IHttpAsyncHandler和ajax请求。

异步请求允许您延迟请求的响应,直到发生外部事件 用户调用此处理程序并等待有人向他发送消息 邮件会在您发送给用户后立即发送。

收到消息后,客户端发出另一个请求并等待下一条消息。 这是保持持久连接打开的方式,并允许服务器将数据推送到客户端。

这比查看网站以检查邮件是否已到达要高效得多 使用异步处理程序还可确保在用户等待消息到来时不会浪费任何asp.net线程。使用计时器进行轮询,您将很快用完线程来处理asp.net中的请求。

这确保即使网站的用户数量增加,您的聊天也可以很好地扩展。

这是completely working project that implements this和ajax。