无刷新的聊天室的制作兼谈组件制作和ClientSide Script
发布时间:2020-12-17 02:58:24 所属栏目:安全 来源:网络整理
导读:我们在传统的web程序当中比较头疼的一件事是屏幕的刷新感。虽然有server push的技术,但在IE中较难实现。现在webservice给了我们这样一个机会,大家都知道webservice是基于soap的,而soap是xml的应用,如果你曾经用过ms xml sdk3.0的话就会知道里面有个xmlht
我们在传统的web程序当中比较头疼的一件事是屏幕的刷新感。虽然有server push的技术,但在IE中较难实现。现在webservice给了我们这样一个机会,大家都知道webservice是基于soap的,而soap是xml的应用,如果你曾经用过ms xml sdk3.0的话就会知道里面有个xmlhttp方法,其实在那时我们就已经可以用xmlhttp的方式替代Form了,也是无刷新的,其实准确地说是局部刷新,下面我们来看一下怎样做,先做一个chat webservice,首先来分析一下,一个聊天室应具备的两个要素人和消息,这样我们可以建立一个类型(记得我在以前说过类也是类型),它包含这样两个要素。 ///ChatMessage.cs using System; namespace chat { /// <summary> /// ChatMessage类封装了两个string变量:UserLists--用户列表,Messages--要传递的信息 /// </summary> public class ChatMessage { public string UserList,Messages; } } 第二个我们要建立的是什么呢?一个聊天室应能存储在线成员的名字及访问时间 ///Member.cs using System; namespace chat { /// <summary> /// Member类为每个聊天者封装了Server端的变量 /// </summary> public class Member { // 存储消息的队列 public string UserName,MsgQueue; // 判断滞留事件以便踢人 public System.DateTime LastAccessTime; // The constructor public Member(string NickName) { this.UserName=NickName; this.LastAccessTime=DateTime.Now; } } } 接下来我们就应该做这个asmx了 ///ChatWebService.asmx using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Web; using System.Web.Services; namespace chat { /// <summary> /// Summary description for ChatWebService. /// </summary> [WebService (Namespace = "http://localhost/chat/",Description = "This service provides an chat service")] public class ChatWebService : System.Web.Services.WebService { public ChatWebService() { //CODEGEN: This call is required by the ASP.NET Web Services Designer InitializeComponent(); } #region Component Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { } #endregion /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { } [WebMethod(Description="接收用户名作为参数存储到Application对象中")] public string Login(string username) { // Ascertain that all the registered chat participants are active CheckMembersList(); // Synchronization Lock Application.Lock(); // Get the collection of keys for the Application Variables String[] Members = Application.AllKeys; // Are there any registered chat members? & the present request is for a unique nick name? if ((Members.Length>0)&&(Array.IndexOf(Members,username)>-1)) { throw new Exception("该用户已存在!"); } // Create a new Member object for this participant Member NewMember = new Member(username); // Add this new member to the collectionof Application Level Variables Application.Add(username,NewMember); // Synchronization unlock Application.UnLock(); // Go and get the list of current chat participants and retrun the list return GetMembersList(); } [WebMethod(Description="GetMsg方法用用户名和消息为参数返回一个ChatMessage对象,包括要传递的消息和用户列表")] public ChatMessage XchangeMsgs(string username,string Msg) { // Ascertain that all the registered chat participants are active CheckMembersList(); // Synchronization Lock Application.Lock(); // Get the collection of keys for the Application Variables String[] Members = Application.AllKeys; if ((Members.Length==0)||(Array.IndexOf(Members,username)==-1)) // Are there any registered chat members? & the present request is for a unique nick name? { throw new Exception("你当前可能没有登陆或登陆超时,请重新登陆!"); } ChatMessage RetMsg = new ChatMessage(); RetMsg.UserList = GetMembersList(); // Loop through all the Chat Participant's serverside Member Objects and // add the message just received in their waiting message queue for (int x=0;x<Members.Length;x++) { Member temp = (Member)Application[Members[x]]; temp.MsgQueue+=("<BR><Font color = Red>" + username + " 说:<BR></FONT><Font color = Blue>" + Msg); if (temp.UserName == username) { RetMsg.Messages = temp.MsgQueue; temp.MsgQueue=""; temp.LastAccessTime=DateTime.Now; } } // Synchronization unlock Application.UnLock(); return RetMsg; } [WebMethod(Description="GetMsg方法用username为参数返回一个ChatMessage对象,包括要传递的消息和用户列表")] public ChatMessage GetMsgs(string username) { Application.Lock(); CheckMembersList(); Application.Lock(); String[] Members = Application.AllKeys; if ((Members.Length==0)||(Array.IndexOf(Members,username)==-1)) { throw new Exception("Unknown User. Please Login with a UserName"); } ChatMessage RetMsg = new ChatMessage(); RetMsg.UserList = GetMembersList(); Member temp = (Member)Application[username]; RetMsg.Messages = temp.MsgQueue; temp.MsgQueue=""; temp.LastAccessTime=DateTime.Now; Application.UnLock(); return RetMsg; } public string GetMembersList() { Application.Lock(); String UserList = ""; String[] Members = Application.AllKeys; Application.UnLock(); for (int x=0;x<Members.Length;x++) { Member temp = (Member)Application[Members[x]]; UserList += (temp.UserName+"/n"); } return UserList; } private void CheckMembersList() { String[] Members = Application.AllKeys; ArrayList RemoveList = new ArrayList(); for (int x=0;x<Members.Length;x++) { Member temp = (Member) Application[Members[x]]; int test = (DateTime.Now.Subtract(temp.LastAccessTime)).Minutes; if (test > 2) { RemoveList.Add(Members[x]); } } // Users = null; for (int count = 0;count<RemoveList.Count;count++) { Application.Remove((String)RemoveList[count]); } return; } } } 好了,至此,我们的webservice就完成了,大家可能不满了,还是没实现无刷新嘛,别急,这是客户端的事。下面我们就来做这项工作。 一般来说我们完全可以做一个html页面,而不用server page,但为了顺便说明怎样做组件,我决定作一个server control,先来看一下代码 using System; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; using System.ComponentModel; namespace Michael.Web.UI.Controls { /// <summary> /// Summary description for chat. /// </summary> [DefaultProperty("Text"),ToolboxData("<{0}:chat runat=server></{0}:chat>")] public class chat : System.Web.UI.WebControls.Table { private string doc; private string text; [Bindable(true),Category("Appearance"),Defaultvalue("")] public string Text { get { return text; } set { text = value; } } /// <summary> /// Render this control to the output parameter specified. /// </summary> /// <param name="output"> The HTML writer to write out to </param> protected override void Render(HtmlTextWriter output) { // The script block is written to the client output.Write(doc); base.Render(output); } private string Serviceurl = "http://localhost/chat/ChatWebService.asmx?WSDL"; [Bindable(true),Category("WebServiceProperty"),Defaultvalue("http://localhost/chat/ChatWebService.asmx?WSDL")] public string ServiceURL { get { return Serviceurl; } set { Serviceurl = value; } } private string Behaviorurl = "http://localhost/chat/webservice.htc"; [Bindable(true),Defaultvalue("")] public string BehaviorURL { get { return Behaviorurl; } set { Behaviorurl = value; } } private string tablecssclass; [Bindable(true),Category("LayoutProperty"),Defaultvalue("")] public string TableCssClass { get { return tablecssclass; } set { tablecssclass = value; } } private string titlecssclass; [Bindable(true),Defaultvalue("")] public string TitleCssClass { get { return titlecssclass; } set { titlecssclass = value; } } private string onlinecssclass; [Bindable(true),Defaultvalue("")] public string OnlineCssClass { get { return onlinecssclass; } set { onlinecssclass = value; } } private string msgcssclass; [Bindable(true),Defaultvalue("")] public string MSGCssClass { get { return msgcssclass; } set { msgcssclass = value; } } private string selusercssclass; [Bindable(true),Defaultvalue("")] public string SelUserCssClass { get { return selusercssclass; } set { selusercssclass = value; } } protected override void OnInit(EventArgs e) { this.ID = "service"; this.Style["Behavior"] = "url('" + Behaviorurl + "')"; this.Style["Table-Layout"] = "Fixed"; if( this.Attributes["class"] == null) this.Attributes["class"] = tablecssclass; this.Attributes["onresult"] = UniqueID + "_onmyresult();"; TableRow tr; // And also create 7 Table Cell elements one by one TableCell cell = new TableCell(); cell.Attributes["class"] = titlecssclass; cell.Attributes["Align"] = "Left"; // Set the caption of the control cell.Text = "Portal 聊天室"; // Instantiate a Table Roa and attach the First Cell to it tr = new TableRow(); tr.Cells.Add(cell); // Add the Table Row to our Control this.Rows.Add(tr); // Row No 2 starts here cell = new TableCell(); cell.Attributes["class"] = onlinecssclass; cell.Text = "在线人员"; tr = new TableRow(); tr.Cells.Add(cell); this.Rows.Add(tr); // Row No 3 Starts here cell = new TableCell(); cell.Style["Height"] = "25%"; // We create a DIV element using HtmlGenericControl object // We can also do this using the Panel object HtmlGenericControl d = new HtmlGenericControl("Div"); d.ID = UniqueID + "_ChatMsgs"; d.Style["Height"] = "100%"; d.Style["Width"] = "100%"; d.Style["Overflow"] = "Auto"; d.Style["Padding-Left"] = "15%"; d.ID = UniqueID + "_ChatList"; // Adding the DIV element to the Table Cell cell.Controls.Add(d); tr = new TableRow(); tr.Cells.Add(cell); this.Rows.Add(tr); // Row No 4 Starts here cell = new TableCell(); cell.Attributes["class"] = msgcssclass; cell.Text = "消息:"; tr = new TableRow(); tr.Cells.Add(cell); this.Rows.Add(tr); // Row No 5 starts here cell = new TableCell(); cell.Style["Height"] = "35%"; d = new HtmlGenericControl("Div"); d.ID = UniqueID + "_ChatMsgs"; d.Style["Height"] = "100%"; d.Style["Width"] = "100%"; d.Style["Overflow"] = "Auto"; cell.Controls.Add(d); tr = new TableRow(); tr.Cells.Add(cell); this.Rows.Add(tr); // Row No 6 Starts here cell = new TableCell(); cell.Attributes["class"] = selusercssclass; cell.ID = UniqueID + "_Prompt"; cell.Text = "选择一个用户:"; tr = new TableRow(); tr.Cells.Add(cell); this.Rows.Add(tr); // Row No 7 starts here cell = new TableCell(); cell.Text = "<INPUT Type=/"Text/" id= '" + UniqueID + "_UserInput'> /r/n"; cell.Text += "<BR>/r/n"; cell.Text += "<Button id = '" + UniqueID + "_bnSendMsg' onclick = /"return SendMsg();/" class = " + UniqueID + "_TitleLabel style = /"display:none/"> 发送 </Button>/r/n"; cell.Text += "<Button id = '" + UniqueID + "_bnSelectName' onclick = /"return " + UniqueID + "_SelectName();/" class = " + UniqueID + "_TitleLabel style = /"display:block/"> 登陆 </Button> /r/n"; cell.Style["Color"] = "Black"; cell.Style["Background-Color"] = "Gainsboro"; tr = new TableRow(); tr.Cells.Add(cell); this.Rows.Add(tr); // First script Block is written into 'doc' variable doc = "/r/n<SCRIPT FOR = 'window' EVENT = 'onload()'>"; doc += "//alert(/"done/"); /r/n"; doc += "service.use(/""; doc += Serviceurl + "/",/"ChatWebService/"); /r/n"; doc += "" + UniqueID + "_UserInput.focus();/r/n"; doc += "</SCRIPT> /r/n"; // Then the second script block follows doc += "<script language=/"javascript/">/r/n"; doc += "var " + UniqueID + "_iCallID1," + UniqueID + "_iCallID2," + UniqueID + "_iCallID3; /r/n"; doc += "var " + UniqueID + "_NickName; /r/n"; doc += "var " + UniqueID + "_MsgXML = new ActiveXObject(/"MSXML.DOMdocument.");/r/n"; doc += "function " + UniqueID + "_SelectName() /r/n"; doc += "{ /r/n"; doc += "if (" + UniqueID + "_UserInput.value == /"/") return false;/r/n"; doc += "" + UniqueID + "_NickName = " + UniqueID + "_UserInput.value; /r/n"; doc += "" + UniqueID + "_bnSelectName.disabled = 'true'; /r/n"; doc += "" + UniqueID + "_UserInput.disabled = 'true';/r/n"; doc += "" + UniqueID + "_iCallID1 = service.ChatWebService.call(/"Login/"," + UniqueID + "_NickName); /r/n"; doc += "} /r/n"; doc += "function " + UniqueID + "_onmyresult() /r/n"; doc += "{ /r/n"; doc += "if((event.result.error)&&(" + UniqueID + "_iCallID1==event.result.id)) /r/n"; doc += "{ /r/n"; doc += "var xfaultcode = event.result.errorDetail.code; /r/n"; doc += "var xfaultstring = event.result.errorDetail.string; /r/n"; doc += "var xfaultsoap = event.result.errorDetail.raw;/r/n"; doc += "/r/n"; doc += "// Add code to output error information here/r/n"; doc += "alert(xfaultstring);/r/n"; doc += "" + UniqueID + "_bnSelectName.disabled = false;/r/n"; doc += "" + UniqueID + "_UserInput.disabled = false; /r/n"; doc += "" + UniqueID + "_UserInput.focus();/r/n"; doc += "/r/n"; doc += "} /r/n"; doc += "else if((!event.result.error)&&(" + UniqueID + "_iCallID1==event.result.id)) /r/n"; doc += "{ /r/n"; doc += "" + UniqueID + "_ChatList.innerText= event.result.value; /r/n"; doc += "" + UniqueID + "_ChatList.scrollTop = 2000; /r/n"; doc += "" + UniqueID + "_bnSelectName.style.display = 'none';/r/n"; doc += "" + UniqueID + "_bnSendMsg.style.display = 'block';/r/n"; doc += "" + UniqueID + "_UserInput.value = /"/"; /r/n"; doc += "" + UniqueID + "_UserInput.disabled = false; /r/n"; doc += "" + UniqueID + "_UserInput.focus();/r/n"; doc += "" + UniqueID + "_Prompt.innerText = " + UniqueID + "_NickName + /" 说:/"; /r/n"; doc += "window.setTimeout('" + UniqueID + "_iCallID2 = service.ChatWebService.call(/"GetMsgs/"," + UniqueID + "_NickName);',3000); /r/n"; doc += "} /r/n"; doc += "else if((event.result.error)&&(" + UniqueID + "_iCallID2==event.result.id))/r/n"; doc += " {/r/n"; doc += "var xfaultcode = event.result.errorDetail.code; /r/n"; doc += "var xfaultstring = event.result.errorDetail.string; /r/n"; doc += "var xfaultsoap = event.result.errorDetail.raw;/r/n"; doc += "// Add code to output error information here/r/n"; doc += "alert(/"xfaultstring/");/r/n"; doc += " }/r/n"; doc += " else if((!event.result.error)&&(" + UniqueID + "_iCallID2==event.result.id))/r/n"; doc += " {/r/n"; doc += "var xmlResult = event.result.raw.xml; /r/n"; doc += " if (xmlResult != /"/" && xmlResult != null)/r/n"; doc += " {/r/n"; doc += "/r/n"; doc += "" + UniqueID + "_MsgXML.loadXML(xmlResult);/r/n"; doc += " " + UniqueID + "_ChatList.innerText = " + UniqueID + "_MsgXML.selectSingleNode(/"//UserList/").text; /r/n"; doc += "" + UniqueID + "_ChatList.scrollTop = 2000; /r/n"; doc += " " + UniqueID + "_ChatMsgs.innerHTML += " + UniqueID + "_MsgXML.selectSingleNode(/"//Messages/").text;/r/n"; doc += "" + UniqueID + "_ChatMsgs.scrollTop = 2000; /r/n"; doc += " }/r/n"; doc += " window.setTimeout('" + UniqueID + "_iCallID2 = service.ChatWebService.call(/"GetMsgs/",3000);/r/n"; doc += " }/r/n"; doc += "else if((event.result.error)&&(" + UniqueID + "_iCallID3==event.result.id))/r/n"; doc += " {/r/n"; doc += "var xfaultcode = event.result.errorDetail.code; /r/n"; doc += "var xfaultstring = event.result.errorDetail.string; /r/n"; doc += "var xfaultsoap = event.result.errorDetail.raw;/r/n"; doc += "// Add code to output error information here/r/n"; doc += "alert(/"xfaultstring/");/r/n"; doc += " }/r/n"; doc += " else if((!event.result.error)&&(" + UniqueID + "_iCallID3==event.result.id))/r/n"; doc += " {/r/n"; doc += "var xmlResult = event.result.raw.xml; /r/n"; doc += " if (xmlResult != /"/" && xmlResult != null)/r/n"; doc += " {/r/n"; doc += "/r/n"; doc += "" + UniqueID + "_MsgXML.loadXML(xmlResult);/r/n"; doc += " " + UniqueID + "_ChatList.innerText = " + UniqueID + "_MsgXML.selectSingleNode(/"//UserList/").text; /r/n"; doc += " " + UniqueID + "_ChatMsgs.innerHTML += " + UniqueID + "_MsgXML.selectSingleNode(/"//Messages/").text;/r/n"; doc += " " + UniqueID + "_ChatList.scrollTop = 2000; /r/n"; doc += " " + UniqueID + "_bnSendMsg.disabled = false;/r/n"; doc += " " + UniqueID + "_ChatMsgs.scrollTop = 2000; /r/n"; doc += " " + UniqueID + "_UserInput.value = /"/";/r/n"; doc += " " + UniqueID + "_UserInput.disabled = false;/r/n"; doc += " " + UniqueID + "_UserInput.focus();/r/n"; doc += " }/r/n"; doc += " window.setTimeout('" + UniqueID + "_iCallID2 = service.ChatWebService.call(/"GetMsgs/",3000);/r/n"; doc += " }/r/n"; doc += "} /r/n"; doc += "function SendMsg()/r/n"; doc += "{ /r/n"; doc += "if (" + UniqueID + "_UserInput.value == /"/") return false;/r/n"; doc += "" + UniqueID + "_bnSendMsg.disabled = 'true';/r/n"; doc += "" + UniqueID + "_UserInput.disabled = 'true';/r/n"; doc += "" + UniqueID + "_iCallID3 = service.ChatWebService.call(/"XchangeMsgs/"," + UniqueID + "_NickName," + UniqueID + "_UserInput.value);/r/n"; doc += "} /r/n"; doc += "</script> /r/n"; } } } 这里有几个问题, 1。我们继承的是Table,记住table等server端控件本身就继承了control类,我们做控件不一定要直接继承control 2。[“。。。”]是metadata他是用来做可视化控件的具体含义看msdn 3。我们这里采用client script的方法,可以看出实现方式与asp中大体一致,即Server端“写”script 4。Dhtml Behavior的应用,Behavior是MS扩展的css元素,大家可去msdn查
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |