在ASP.NET3.5下利用Linq,Ajax创建一个线上网络聊天室

无标题文档 原文:Build a Web Chat Application using ASP.Net 3.5, LINQ and AJAX
英文水平有限,也不想用Google或者Yahoo或者其他翻译工具去逐句翻译,按俺自己的理解去写,希望不要偏离原文的意思(老天保佑~)
创建一个线上聊天室,其实蛮好玩的,又用了感兴趣的Linq,所以才把这篇文章抄到这~
开发环境:ASP.Net 3.5, AJAX, JavaScript, C# 3.5, LINQ-to-SQL, MS SQL Server 2000/2005
聊天室的界面就是这个样子:

目标:
1)好玩,不好玩就不会做这个东东
2)聊天室不需要安装什么就可以登录聊天
3)页面无刷新
4)信息可以保存起来,下次登录还能看到聊天记录
5)使用Linq to Sql来代替存储过程,提高开发速度
6)聊天室不需要太复杂的功能,一个登录页,和一个聊天页就可以了,不想太复杂

好了,Go,GO!
1.在MS SQL Server 2000/2005上创建聊天室数据库,然后建一个聊天室的项目。数据库表结构及说明如下:

  • User: 包含用户的信息. 当然你还可以给User添加诸如 address, city, 获者其他一些字段.
  • Message: 记录用户的聊天信息.
  • Room: 记录聊天室信息. 一个用户可以进入不同的聊天室. 老外为了省事,下面的代码里,假定用户只有一个聊天室.
  • LoggedInUsers: 记录用户登录及聊天的一些信息。借助这个表,我们可以获得用户在一个指定的聊天室的一些信息.

2.打开VS2008,创建一个.NET Framework 3.5的ASP.NET网站。开发语言是:C#

3.建一个登录页,注册页以及登录用户和密码的加密就免了,Just for fun!不考虑那么多了。

4.创建聊天页,效果图及页面元素说明如下:
 

Div tag for Messages: 蓝色的 Div Tag是聊天室的主要部分,显示聊天信息 TextBox: 输入你想说的话. Send Button: 向聊天室发送你刚才输入的话. Div tag for Chatters: 棕色的 Div Tag是显示聊天室内的成员. Log-out Button: 登出目前的聊天室. Update Panel: VS2008已经集成了MS AJAX了,所以这个控件就不想说它在这起什么作用了. Timer Control: 这个控件主要是为了更新聊天室的内容,每隔7秒刷新一次内容.

现在,界面上的完成了,该进入代码阶段了

首先关注下,整个聊天室的工作流程

1.首先,打开web.config,加入用户验证的东东
   50         <authentication mode="Forms">
   51             <forms name=".ASPXAUTH" loginUrl="Default.aspx"/>
   52         </authentication>
   53 
   54         <authorization>
   55             <deny users="?" />
   56         </authorization>

 2.用户登录后由登录页跳转到聊天页时,用户名及密码用Session来保存。这里在跳转后,由于之前假定用户只有一个聊天室,
因此跳转后,会进入聊天室为"room1"的聊天页。如果存在多个聊天室,那么你可以再加一个聊天室的列表页,让用户进入到 这里,由他选择进入哪个聊天室。登录的代码如下:
   13         protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
   14         {
   15             LinqChatDataContext db = new LinqChatDataContext();
   16 
   17             var user = (from u in db.Users
   18                         where u.Username == Login1.UserName
   19                         && u.Password == Login1.Password
   20                         select u).SingleOrDefault();
   21 
   22             if (user != null)
   23             {
   24                 e.Authenticated = true;
   25                 Session["ChatUserID"] = user.UserID;
   26                 Session["ChatUsername"] = user.Username;
   27             }
   28             else
   29             {
   30                 e.Authenticated = false;
   31             }
   32         }
   33 
   34         protected void Login1_LoggedIn(object sender, EventArgs e)
   35         {
   36             Response.Redirect("Chatroom.aspx?roomId=1");
   37         }

3.根据接收到的roomId的值,来确定聊天室的名字,已经聊天室的相关信息,比如成员,聊天记录等等
   16                 // for simplity's sake we're going to assume that a
   17                 // roomId was passed in the query string and that
   18                 // it is an integer
   19                 // note: in reality you would check if the roomId is empty
   20                 // and is an integer
   21                 string roomId = (string)Request["roomId"];
   22                 lblRoomId.Text = roomId;

4.为了通知其他用户,该用户已进入聊天室,所以建立了LoggedInUser 来记录聊天室的一些信息。通过
这个表,我们可以获取聊天室的所有成员及信息。这个操作的代码如下:
   26 this.InsertMessage(ConfigurationManager.AppSettings["ChatLoggedInText"] + " " + DateTime.Now.ToString());

5.InsertMessage的具体代码如下:
   74         private void InsertMessage(string text) 
   75         {
   76             LinqChatDataContext db = new LinqChatDataContext();
   77 
   78             Message message = new Message();
   79             message.RoomID = Convert.ToInt32(lblRoomId.Text);
   80             message.UserID= Convert.ToInt32(Session["ChatUserID"]);
   81 
   82             if (String.IsNullOrEmpty(text))
   83             {
   84                 message.Text = txtMessage.Text.Replace("<", "");
   85                 message.Color = ddlColor.SelectedValue;
   86             }
   87             else
   88             {
   89                 message.Text = text;
   90                 message.Color = "gray";
   91             }
   92 
   93             message.ToUserID = null;            // in the future, we will use this value for private messages
   94             message.TimeStamp = DateTime.Now;
   95             db.Messages.InsertOnSubmit(message);
   96             db.SubmitChanges();
   97         }

同时在web.config里加入以下代码:
   24     <appSettings>
   25         <add key="ChatLoggedInText" value="Just logged in!"/>
   26     </appSettings>

6.完成了新增Message记录后,接下来是完成显示Message的功能了:
  148         /// <summary>
  149         /// Get the last 20 messages for this room
  150         /// </summary>
  151         private void GetMessages()
  152         {
  153             LinqChatDataContext db = new LinqChatDataContext();
  154
  155             var messages = (from m in db.Messages
  156                            where m.RoomID == Convert.ToInt32(lblRoomId.Text)
  157                            orderby m.TimeStamp descending
  158                            select m).Take(20).OrderBy(m => m.TimeStamp);
  159 
  160             if (messages != null)
  161             {
  162                 StringBuilder sb = new StringBuilder();
  163                 int ctr = 0;    // toggle counter for alternating color
  164 
  165                 foreach (var message in messages)
  166                 {
  167                     // alternate background color on messages
  168                     if (ctr == 0)
  169                     {
  170                         sb.Append("<div style='padding: 10px;'>");
  171                         ctr = 1;
  172                     }
  173                     else
  174                     {
  175                         sb.Append("<div style='background-color: #EFEFEF; padding: 10px;'>");
  176                         ctr = 0;
  177                     }
  178 
  179                     if (message.User.Sex.ToString().ToLower() == "m")
  180                         sb.Append("<img src='Images/manIcon.gif' style='vertical-align:middle' alt=''>  " + message.Text + "</div>");
  181                     else
  182                         sb.Append("<img src='Images/womanIcon.gif' style='vertical-align:middle' alt=''>  " + message.Text + "</div>");
  183                 }
  184 
  185                 litMessages.Text = sb.ToString();
  186             }
  187         }

7.当用户登录该聊天室时,右侧的用户列表区必须显示当前聊天室参与的的用户。当你选择某位用户时,你可以和他私聊。
   99         private void GetLoggedInUsers()
  100         {
  101             LinqChatDataContext db = new LinqChatDataContext();
  102 
  103             // let's check if this authenticated user exist in the
  104             // LoggedInUser table (means user is logged-in to this room)
  105             var user = (from u in db.LoggedInUsers
  106                         where u.UserID == Convert.ToInt32(Session["ChatUserID"])
  107                         && u.RoomID == Convert.ToInt32(lblRoomId.Text)
  108                         select u).SingleOrDefault();
  109 
  110             // if user does not exist in the LoggedInUser table
  111             // then let's add/insert the user to the table
  112             if (user == null)
  113             {
  114                 LoggedInUser loggedInUser = new LoggedInUser();
  115                 loggedInUser.UserID = Convert.ToInt32(Session["ChatUserID"]);
  116                 loggedInUser.RoomID = Convert.ToInt32(lblRoomId.Text);
  117                 db.LoggedInUsers.InsertOnSubmit(loggedInUser);
  118                 db.SubmitChanges();
  119             }
  120 
  121             string userIcon;
  122             StringBuilder sb = new StringBuilder();
  123 
  124             // get all logged in users to this room
  125             var loggedInUsers = from l in db.LoggedInUsers
  126                                 where l.RoomID == Convert.ToInt32(lblRoomId.Text)
  127                                 select l;
  128 
  129             // list all logged in chat users in the user list
  130             foreach (var loggedInUser in loggedInUsers)
  131             {
  132                 // show user icon based on sex
  133                 if (loggedInUser.User.Sex.ToString().ToLower() == "m")
  134                     userIcon = "<img src='Images/manIcon.gif' style='vertical-align:middle' alt=''>  ";
  135                 else
  136                     userIcon = "<img src='Images/womanIcon.gif' style='vertical-align:middle' alt=''>  ";
  137 
  138                 if (loggedInUser.User.Username != (string)Session["ChatUsername"])
  139                         sb.Append(userIcon + "<a href=#>" + loggedInUser.User.Username + "</a><br>");
  140                 else
  141                     sb.Append(userIcon + "<b>" + loggedInUser.User.Username + "</b><br>");
  142             }
  143 
  144             // holds the names of the users shown in the chatroom
  145             litUsers.Text = sb.ToString();
  146         }

8.完成上叙代码,现在当你进入聊天室后,系统会把你进入聊天室的消息通知给该聊天室的当前用户。

接着,就是发送聊天信息:

  1. 上文提到用Textbox来输入聊天信息,要控制每次发送消息后,光标位置都在TextBox上,需要在两个位置进行控制,代码如下:
    按钮"Send"点击事件:
       58 ScriptManager1.SetFocus(txtMessage.ClientID);

    另外还有Timer控件的监听事件: 
       68 ScriptManager1.SetFocus(txtMessage);


  2. 当然,有时候你并不会去点击按钮来发送消息,而是直接敲击键盘的回车键(Enter),那么这个时候你要保持光标定位在TextBox上,怎么办呢?代码如下:

    <form id="form1" defaultbutton="btnSend" defaultfocus="txtMessage" runat="server" >

  3. 当你发送一条消息,需要考虑一些问题,列表如下
    • 聊天消息是如何被记录到当前聊天信息区域的.
    • 如何获取已发送的消息.
    • 用户的性别及消息怎样可以一并显示在聊天信息区域. 
    • 其他用户是如何接收到你的状态及消息的.
    • 用户可以查看当前参与的用户(显示除自己以外,所有该聊天室的成员). 为了便于私聊,每个用户是带链接的,点击选择该用户可以进入私聊窗口,但是目前这不是我们考虑,预计在下一个例子里我们会实现该功能.
  4. 由于聊天消息不断增多,所以在聊天信息区域引入滚动条,并控制滚动条始终听聊在该区域的底部,代码如下:

    首先是body:

    <body style="background-color: gainsboro;" onload="SetScrollPosition()" onunload="LogMeOut()">

    控制代码:

    function SetScrollPosition()

    {

          var div = document.getElementById('divMessages');

          div.scrollTop = 100000000000;

    }

登出聊天室:

想退出聊天室,要么点退出按钮,要么直接关了浏览器,^_^

  1. 点退出按钮: 当用户点击退出时,首先从LoggedInUser将该用户删除,然后向聊天消息区域发送信息通知其他用户,该用户下线。

      189         protected void BtnLogOut_Click(object sender, EventArgs e)
      190         {
      191             // log out the user by deleting from the LoggedInUser table
      192             LinqChatDataContext db = new LinqChatDataContext();
      193 
      194             var loggedInUser = (from l in db.LoggedInUsers
      195                                where l.UserID == Convert.ToInt32(Session["ChatUserID"])
      196                                && l.RoomID == Convert.ToInt32(lblRoomId.Text)
      197                                select l).SingleOrDefault();
      198 
      199             db.LoggedInUsers.DeleteOnSubmit(loggedInUser);
      200             db.SubmitChanges();
      201 
      202             // insert a message that this user has logged out
      203             this.InsertMessage("Just logged out! " + DateTime.Now.ToString());
      204 
      205             // clean the session
      206             Session.RemoveAll();
      207             Session.Abandon();
      208 
      209             // redirect the user to the login page
      210             Response.Redirect("Default.aspx");
      211         }


  2. 关闭浏览器: 大多数用户可能不会老实的点退出按钮,而是直接叉掉这个浏览器窗口. 我们可以在客户端捕捉到这个事件, 只需要一点html代码和JavaScript脚本就ok了,代码如下

    <body style="background-color: gainsboro;" onload="SetScrollPosition()" onunload="LogMeOut()">

    JavaScript脚本:

    function LogMeOut()

    {

          LogOutUserCallBack();

    }



    当然,我们还可以从服务端捕捉该事件,从LoggedInUser 删除该用户信息,利用ICallbackEventHandler接口,异步完成该操作

        8    public partial class Chatroom : System.Web.UI.Page, System.Web.UI.ICallbackEventHandler


    利用ICallbackEventHandler提供的方法完成以下两步操作.  "RaiseCallbackEvent" 用于处理以控件为目标的回调事件. 下面是利用该方法,删除用户的LoggedInUsers表的信息.

      220         void  System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
      221         {
      222             _callBackStatus = "failed";
      223 
      224             // log out the user by deleting from the LoggedInUser table
      225             LinqChatDataContext db = new LinqChatDataContext();
      226 
      227             var loggedInUser = (from l in db.LoggedInUsers
      228                                 where l.UserID == Convert.ToInt32(Session["ChatUserID"])
      229                                 && l.RoomID == Convert.ToInt32(lblRoomId.Text)
      230                                 select l).SingleOrDefault();
      231 
      232             db.LoggedInUsers.DeleteOnSubmit(loggedInUser);
      233             db.SubmitChanges();
      234 
      235             // insert a message that this user has logged out
      236             this.InsertMessage("Just logged out! " + DateTime.Now.ToString());
      237 
      238             _callBackStatus = "success";
      239         }


     "GetCallbackResult" 用于获取返回以控件为目标的回调事件的结果. 我们可以声明一个变量来获取该方法返回的处理结果,这里我们对变量赋予"success" 或 "failed" 来标明当前事件的处理结果. 代码如下:

      215         string  System.Web.UI.ICallbackEventHandler.GetCallbackResult()
      216         {
      217             return _callBackStatus;
      218         }


    接下来,我们在Page_Load方法里注册一个脚本事件,以完成这个异步的事件处理.

       29                 // create a call back reference so we can log-out user when user closes the browser
       30                 string callBackReference = Page.ClientScript.GetCallbackEventReference(this, "arg", "LogOutUser", "");
       31                 string logOutUserCallBackScript = "function LogOutUserCallBack(arg, context) { " + callBackReference + "; }";
       32                 Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "LogOutUserCallBack", logOutUserCallBackScript, true);

结语:
老外的文章还是不怎么好翻译,要保证翻译后的文章达到信,达,雅这个高度太难了。不过因为好玩把这篇文章坚持看完,收获还是不小。原文最后还有一些话没翻译,如果想看,点击本文开头就可以找到原文。我就偷下懒了~

代码下载: Click here to download the code

转载于:https://www.cnblogs.com/TomToDo/archive/2008/07/10/1239196.html

开发语言为Asp,服务器脚本为VBScript; AJAX部分采用JQuery框架,功能代码均为原创;数据库暂时采用ACCESS; --------- 程序功能: 多人即时聊天;新信息声音提示;用户自主选择表情和颜色; 管理员删除信息/踢出用户;高强度管理密码; 数据库压缩; --------- 程序特色 特色?没什么特色!普通的ASP、普通的HTML、普通的JavaScript、还有一个普通的程序编写者; 唯有一点----本程序为原创,没有参考任何其他类似程序 --------- 默认管理员和密码都是admin 一、配置 用记事本打开inc文件夹下的conn.asp,注意如下代码 '聊天室配置 dim admins: admins="anlige,admin" '管理员用户,可自行配置,每个管理员以英文逗号(,)分割;无数量限制 dim pwd: pwd="43894a0e21232f297a57a5a743894a0e4a801fc3" '管理密码,所有管理员使用一个密码!本密码经MD5加密 dim adminToFront: adminToFront=false '管理员登录后是否同步显示到前台(注意,如果设置true,则登录后台的同时登录前台,前台无需再用另一账号),建议设置为false dim msgExpires: msgExpires=300 '信息过期时间,以分钟为单位,系统自动删除过期的信息 dim userExpires: userExpires=20 '用户过期时间,以分钟为单位,系统自动踢出20分钟不发言的用户 '结束配置 配置结束后保存! ____________________________________________________注意(关于密码)_____________________________________________________________________ 密码使用特殊MD5加密算法加密,如要修改密码请按如下方法修改: 假如你的聊天室地址为http://www.***.com/chat/ 访问http://www.***.com/chat/getmd5.asp?string=你要设置的密码,例如http://www.***.com/chat/getmd5.asp?string=admin 然后会显示一串字符串,上例的话会显示43894a0e21232f297a57a5a743894a0e4a801fc3 将inc/conn.asp代码中pwd的值修改为显示的字符串,保存!下次管理员登录就可以用admin这个作为密码登录,建议修改密码后移动getmd5.asp文件 _______________________________________________________________________________________________________________________________________ 二、使用 聊天室默认地址为index.html,直接访问http://www.***.com/chat/index.html即可进入聊天室 具体使用方法请参考help.html 本程序皮肤使用的是QQ2008的聊天皮肤,有兴趣可以自己做皮肤,注意布局! 三、关于 您可以免费使用本程序,请保留代码中的注释信息,谢谢! 请勿利用本程序来实施任何违反法律的行为;否则,一切后果自负! 请保留作者版权信息,尽管不是什么大程序,但作者近期发现很多使用者连开发人都改成自己的名字,这既是对别人劳动成果的不尊重,也是一个人素质的体现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值