无刷新的聊天室的制作兼谈组件制作和ClientSide Script

我们在传统的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),
Category("WebServiceProperty"),
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),
Category("LayoutProperty"),
Defaultvalue("")]
public string TitleCssClass
{
get
{
return titlecssclass;
}
set
{
titlecssclass = value;
}
}

private string onlinecssclass;
[Bindable(true),
Category("LayoutProperty"),
Defaultvalue("")]
public string OnlineCssClass
{
get
{
return onlinecssclass;
}
set
{
onlinecssclass = value;
}
}

private string msgcssclass;
[Bindable(true),
Category("LayoutProperty"),
Defaultvalue("")]
public string MSGCssClass
{
get
{
return msgcssclass;
}
set
{
msgcssclass = value;
}
}

private string selusercssclass;
[Bindable(true),
Category("LayoutProperty"),
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/"," + UniqueID + "_NickName);',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/"," + UniqueID + "_NickName);',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查
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值