这里要说明的就是主要根据Session_End来对用户做离线操作,退出时也会调用 Session.Abandon();来触发Session_End()事件。具体的时时精确度,主要根据设置的Session过期时间有关系,默认20分钟。也就好比用户停留在页面20分钟不做任何操作,或者直接非正常关闭浏览器,session过期时间到后都会触发移除在线用户。
新建类MemberInfo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
namespace ClassLibrary1
{
public class MemberInfo
{
public string memberName { get; set; }
public DateTime LoginTime { get; set; }
public DateTime? RefreshTime { get; set; }
public static void CreateCacheOnLine()
{
Dictionary<string, string> DD = new Dictionary<string, string>();
if (HttpContext.Current.Cache["cacheName"] != null)
{
DD = (Dictionary<string, string>)HttpContext.Current.Cache["cacheName"];
if (DD.ContainsKey(HttpContext.Current.Session.SessionID))
{
DD.Remove(HttpContext.Current.Session.SessionID);
}
}
DD.Add(HttpContext.Current.Session.SessionID, HttpContext.Current.User.Identity.Name);
HttpContext.Current.Cache.Insert("cacheName", DD, null, DateTime.Now.AddMinutes(60), System.Web.Caching.Cache.NoSlidingExpiration);
}
public static List<string> GetUserList()
{
return new List<string>()
{
"aa1",
"aa2",
"aa3",
"aa4"
};
}
}
}
Golbal.asax类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using ClassLibrary1;
namespace WebApplication8
{
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
}
protected void Session_Start(object sender, EventArgs e)
{
Application.Lock();
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
MemberInfo.CreateCacheOnLine();
}
Application.UnLock();
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
}
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
}
protected void Application_Error(object sender, EventArgs e)
{
}
protected void Session_End(object sender, EventArgs e)
{
Application.Lock();
Dictionary<string, string> dd = (Dictionary<string, string>)System.Web.HttpRuntime.Cache["cacheName"];
if (dd.ContainsKey(Session.SessionID))
{
dd.Remove(Session.SessionID);
}
System.Web.HttpRuntime.Cache.Remove("cacheName");
System.Web.HttpRuntime.Cache.Insert("cacheName", dd, null, DateTime.Now.AddMinutes(60), System.Web.Caching.Cache.NoSlidingExpiration);
Application.UnLock();
}
protected void Application_End(object sender, EventArgs e)
{
}
}
}
Handler1.ashx
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ClassLibrary1;
namespace WebApplication8
{
/// <summary>
/// Handler1 的摘要说明
/// </summary>
public class Handler1 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
System.Text.StringBuilder sb = new System.Text.StringBuilder();
Dictionary<string, string> dd = (Dictionary<string, string>)context.Cache["cacheName"];
sb.Append("{\"userList\":[");
foreach(var userList in MemberInfo.GetUserList())
{
if (dd.Values.Contains(userList))
sb.Append("{\"memberName\":\""+userList+"\",\"onLine\":\"yes\"},");
else
sb.Append("{\"memberName\":\"" + userList + "\",\"onLine\":\"no\"},");
}
sb.Remove(sb.Length-1, 1);
sb.Append("]}");
context.Response.Write(sb.ToString());
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
WebForm1.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication8.WebForm1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<form id="Form1" runat="server">
<div class="top">
</div>
<div class="dashboardAll">
<div class="loginBox">
<p class="ml30"><img src="images/logo.png" alt=""></p>
<div class="loginList">
<p><asp:TextBox ID="txtName" runat="server" CssClass="loginInput" Text="Username or email" οnfοcus="if(value=='Username or email') {value=''}" οnblur="if (value=='') {value='Username or email'}"></asp:TextBox>
<asp:RequiredFieldValidator ID="rfvName" display="Dynamic" ControlToValidate="txtName" style="color:Red;" runat="server" ErrorMessage="You can't leave this empty."></asp:RequiredFieldValidator>
</p>
<p class="pt16 clear"><asp:TextBox ID="txtPwd" runat="server" CssClass="loginInput" TextMode="Password"></asp:TextBox>
<asp:RequiredFieldValidator ID="rfvPwd" display="Dynamic" ControlToValidate="txtPwd" style="color:Red;" runat="server" ErrorMessage="You can't leave this empty."></asp:RequiredFieldValidator>
</p>
<p class="pt16 clear"><asp:CheckBox ID="CheckBoxRememberMe" runat="server" /><span class="pl10">Remember me</span><span class="ml20">
<asp:Button ID="btnLogin" runat="server" CssClass="blueBtn w100" Text="Log in" οnclick="btnLogin_Click" /></span></p>
</div>
</div>
</div>
<p class="clear"></p>
<!-- <div class="foot">
</div> -->
</form>
</body>
</html>
WebForm1.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using ClassLibrary1;
namespace WebApplication8
{
public partial class WebForm1 : System.Web.UI.Page
{
private static object o = new object();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (Request.Cookies["Name"] != null && Request.Cookies["Password"] != null)
{
this.txtName.Text = Request.Cookies["Name"].Value;
this.txtPwd.Attributes["value"] = Request.Cookies["Password"].Value;
}
}
}
protected void btnLogin_Click(object sender, EventArgs e)
{
if (MemberInfo.GetUserList().Contains(this.txtName.Text))
{
Response.Cookies["Name"].Expires = DateTime.Now.AddDays(-1);
Response.Cookies["Password"].Expires = DateTime.Now.AddDays(-1);
if (CheckBoxRememberMe.Checked)
{
Response.Cookies["Name"].Expires = DateTime.Now.AddDays(7);
Response.Cookies["Password"].Expires = DateTime.Now.AddDays(7);
}
Response.Cookies["Name"].Value = this.txtName.Text.Trim();
Response.Cookies["Password"].Value = this.txtPwd.Text.Trim();
var ticket = new System.Web.Security.FormsAuthenticationTicket(1, this.txtName.Text, DateTime.Now, DateTime.Now.AddDays(1), false, "USER");
var encryptedTicket = System.Web.Security.FormsAuthentication.Encrypt(ticket);
if (Request.Cookies[System.Web.Security.FormsAuthentication.FormsCookieName] != null)
Request.Cookies.Remove(System.Web.Security.FormsAuthentication.FormsCookieName);
var loginIdentify = new HttpCookie(System.Web.Security.FormsAuthentication.FormsCookieName);
loginIdentify.Expires = DateTime.Now.AddDays(1);
loginIdentify.Value = encryptedTicket;
Response.AppendCookie(loginIdentify);
lock (o)
{
CreateCacheOnLine();
}
if (!String.IsNullOrEmpty(Request.QueryString["ReturnUrl"]) && !Request.QueryString["ReturnUrl"].ToLower().Contains("profile"))
Response.Redirect(Server.UrlDecode(Request.QueryString["ReturnUrl"]));
else
Response.Redirect(System.Web.Security.FormsAuthentication.DefaultUrl);
}
}
public void CreateCacheOnLine()
{
Dictionary<string, string> DD = new Dictionary<string, string>();
if (HttpContext.Current.Cache["cacheName"] != null)
{
DD = (Dictionary<string, string>)HttpContext.Current.Cache["cacheName"];
if (DD.ContainsKey(HttpContext.Current.Session.SessionID))
{
DD.Remove(HttpContext.Current.Session.SessionID);
}
}
DD.Add(HttpContext.Current.Session.SessionID,this.txtName.Text);
HttpContext.Current.Cache.Insert("cacheName", DD, null, DateTime.Now.AddMinutes(60), System.Web.Caching.Cache.NoSlidingExpiration);
}
}
}
webForm2.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="WebApplication8.WebForm2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript" src="Scripts/jquery-1.4.1.min.js"></script>
<script type="text/javascript">
function OnLine() {
$.getJSON("Handler1.ashx", null, function (data) {
$("#tbUserList").html("");
var str = "<tr><td>memberName</td><td>是否在线</td></tr>";
$.each(data.userList, function (i, item) {
if (item.onLine == "yes")
str += "<tr><td>" + item.memberName + "</td><td>在线</td></tr>";
else
str += "<tr><td>" + item.memberName + "</td><td>离线</td></tr>";
});
$("#tbUserList").append(str);
})
}
window.setInterval(OnLine, 1000);
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<table id="tbUserList">
</table>
<asp:Button ID="Button1" runat="server" Text="退出" οnclick="Button1_Click" />
</div>
</form>
</body>
</html>
WebForm2.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using ClassLibrary1;
using System.Web.Security;
namespace WebApplication8
{
public partial class WebForm2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
FormsAuthentication.SignOut();
Session.Abandon();
Response.Redirect(Request.Url.ToString());
}
}
}