以前工作项目中就有一个微博类功能,其中也出现了用户在线和离线的问题。

但是因为初入程序猿 使用的是 Session _end 上个事件。 Session _end 这个事件不需要怎么解释吧 就是在seesion过期的时候所触发的事件,但有BUG啊! 因为 iis 中由于有进程回收机制,系统繁忙的话Session会丢失。 当然 微软解决又弄了个 进程外seesion 来解决了一下 。额 当时楞是没想起来为啥 ,还是经验少啊。

今天突然看了些  在线状态的问题  突发奇想   想自己不适用Seesion _end  来做一个 在线状态的实现。  百度了半天 还是没啥收获,最后决定  得  自己写吧!

首先想到就是 利用静态对象  得特性 (在程序执行前就创建好对象并且知道程序结束之前不会被释放掉。)前几天从新看了一下进程和线程   进程和线程执行是通过操作系统维护的一个进程表维护着的 调度器  调整执行的。 所以就联想到 在管道事件 Application_Start() 中来维护一个 静态集合对象 通过定时器 实现 session_end 这个事件

Globel.asax.cs 文件中添加一个事件

 public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// 开启一个定时器 并且执行一个方法
StatusMy.GetStatusMy().TestTimer(); }
}
 StatusMy 对象类 是关键的问题   代码并不多 应该很好理解  
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web; namespace OnlineStatus.Models
{
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Validation; using OnlineStatus.Models.Model; public class StatusMy : System.Web.HttpApplication
{
#region 单例
private StatusMy()
{
} private static StatusMy IStatusMy; public static StatusMy GetStatusMy()
{
return IStatusMy ?? (IStatusMy = new StatusMy());
}
#endregion /// <summary>
/// 定义定时器 如果是public 很有可能被GC掉
/// </summary>
private System.Threading.Timer timerClose; /// <summary>
/// 定义个静态集合
/// </summary>
private static List<MyUser> listMy; /// <summary>
/// 定义一个 Lock 的时候使用的 Object 可以使用this 但是如果当前的这个this 是public 的话会有可能出现异常 保险期间还是使用MSDN 官方
/// </summary>
private object thisLock = new object(); /// <summary>
/// 执行定时器
/// </summary>
public void TestTimer()
{
timerClose = new System.Threading.Timer(ToMyContent, null, , );
} /// <summary>
/// 利用Application的特性 维护一个 集合表 表中记录了最后一次网站时间 如果最后一次访问时间 小于服务器时间20分钟者在数据库中设置为 离线状态
/// </summary>
/// <param name="o">
/// The o.
/// </param>
private void ToMyContent(object o)
{
if (listMy == null || listMy.Count <= )
{
return;
} DbContext db = MyDbContext.GetCurrentEFContext();//使用的是CallContxt 确保当前进程内唯一 // 定义一个变量用来判断 维护着的List 对象是否有值 方便最后EF统一执行SQL 语句
int i = ;
foreach (MyUser myContent in listMy)
{
TimeSpan s = new TimeSpan(, , , );// 这是时间差为20分钟 System.TimeSpan ts = DateTime.Now.Subtract(myContent.UTime); //通过当前服务器时间减去用户最后一次访问服务器的时间的出来的 时间差 if (ts < s)
{
continue; // 跳出这次循环 不执行 if 后续代码
} // 做修改标注
User u = new User { ID = myContent.ID, Status = false, UTime = myContent.UTime, Name = myContent.Name };
DbEntityEntry<User> entry = db.Entry<User>(u);
entry.State = System.Data.EntityState.Modified;
entry.Property(a => a.Status).IsModified = true; i++;
} if (i == )
{
return;
} try
{
db.SaveChanges();
}
catch (DbEntityValidationException dbEx)
{ }
} /// <summary>
/// 用户访问的 将其添加维护到 集合中
/// </summary>
/// <param name="u"></param>
public void AddList(User u)
{
if (u == null && u.ID <= )
return; MyUser myU = new MyUser { ID = u.ID, Name = u.Name, UTime = DateTime.Now, Status = u.Status }; if (listMy == null)
{
lock (thisLock)
{
listMy = new List<MyUser> { myU };
} return;
} MyUser m = listMy.FirstOrDefault(c => c.ID == myU.ID);
if (m != null && m.ID != )
{
lock (thisLock)
{
listMy.Remove(m);
listMy.Add(myU);
}
}
else
{
lock (thisLock)
{
listMy.Add(myU);
}
}
}
}
}

MyDbContext类   线程唯一   EF上下文的问题 你懂的

public  static class MyDbContext
{
public static DbContext GetCurrentEFContext()
{ DbContext dbContext = CallContext.GetData("EFContext") as DbContext;
if (dbContext==null)
{
dbContext = new Model1Container();
dbContext.Configuration.ValidateOnSaveEnabled = true;
CallContext.SetData("EFContext", dbContext);
}
return dbContext; }
}

MVC 的全局过滤器  可以做到  不管用户访问那个服务器页面 都可以进行操作。 额  面向切面编程?

在 FilterConfig 类中添加过滤器类

 public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute()); filters.Add(new OnlineStatus.Controllers.LoginValidateAttribute());
}
}

LoginValidateAttribute  自定义过滤器的实现

 public class LoginValidateAttribute : System.Web.Mvc.AuthorizeAttribute
{ public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
{ // 判断 请求的 控制器是不是等于指定的控制器 如果不留下一个不用验证的控制器 那么就会一直在服务器跳转
if (filterContext.RouteData.Values["controller"].ToString() != "RegisterLogin")
{
#region 1.验证用户是否登陆(Session && Cookie)
//1.验证用户是否登陆(Session && Cookie)
if (!OnlineStatus.Controllers.Help.ToHelp().IsLogin())
{
filterContext.Result = filterContext.Result = new RedirectResult("/RegisterLogin/index");
}
#endregion
} }
}
ToHelp 类 的实现 
 public class Help
{ private Help()
{ } private static Help Ihelp; public static Help ToHelp()
{
return Ihelp ?? (Ihelp = new Help());
} #region 0.1 Http上下文 及 相关属性
/// <summary>
/// Http上下文
/// </summary>
HttpContext ContextHttp
{
get
{
return HttpContext.Current;
}
} HttpResponse Response
{
get
{
return ContextHttp.Response;
}
} HttpRequest Request
{
get
{
return ContextHttp.Request;
}
} System.Web.SessionState.HttpSessionState Session
{
get
{
return ContextHttp.Session;
}
}
#endregion #region 2.1 当前用户对象 +MODEL.Ou_UserInfo Usr
// <summary>
/// 当前用户对象
/// </summary>
public Models.User Usr
{
get
{
return Session["name"] as Models.User;
}
set
{
Session["name"] = value;
}
}
#endregion /// <summary>
/// 验证用户是否登录
/// </summary>
/// <returns></returns>
public bool IsLogin()
{
if (Session["name"] == null)
{
if (Request.Cookies["name"] == null)
{
return false;
}
string strUser = Request.Cookies["name"].Value; int userid = int.Parse(strUser); DbContext db = MyDbContext.GetCurrentEFContext();
OnlineStatus.Models.User use = db.Set<OnlineStatus.Models.User>().FirstOrDefault(c => c.ID == userid);
if (use == null && use.ID <= )
{
return false;
}
Usr = use; //将其添加到维护的 状态集合中
StatusMy.GetStatusMy().AddList(use); }
return true;
} /// <summary>
/// 登录 这里就简单写了 名称密码都对 就true 不对 false 额 以为是想简单写一下 数据库居然没弄密码 额
/// </summary>
/// <param name="name"></param>
/// <param name="pwd"></param>
/// <returns></returns>
public bool Login(string name)
{
DbContext db = MyDbContext.GetCurrentEFContext();
OnlineStatus.Models.User use = db.Set<OnlineStatus.Models.User>().FirstOrDefault(c => c.Name == name);
if (use == null && use.ID >= )
{
return false;
}
//将其添加到维护的 状态集合中
StatusMy.GetStatusMy().AddList(use);
return true;
} }
我试了试 OK    

 一直都是自己一个人研究来研究去的 冒泡出来   纯粹是来 希望和大神们交流一下 ,请大神们指点一下。 

不喜勿喷。 
看帖 求评论啊, 真的很希望能有人 指点指点啊

解决 MVC 用户上线下线状态问题的更多相关文章

  1. C# MVC 用户登录状态判断 【C#】list 去重(转载) js 日期格式转换(转载) C#日期转换(转载) Nullable<System.DateTime>日期格式转换 (转载) Asp.Net MVC中Action跳转(转载)

    C# MVC 用户登录状态判断   来源:https://www.cnblogs.com/cherryzhou/p/4978342.html 在Filters文件夹下添加一个类Authenticati ...

  2. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(九) 之 用 Redis 实现用户在线离线状态消息处理(一)

    前言 上一篇中简单讲解了用Redis缓存在线用户逻辑.篇幅也比较小,本篇将详细实现用户的上线下线通知.图片效果转换功能.而且,代码和开发思路都会详细介绍. 效果展示 目前有三个用户,user1,use ...

  3. Postman+Postman interceptor的安装和使用-解决把chrome浏览器登录状态同步到postman进行有依赖的接口测试 Postman 使用方法详解

    Postman+Postman interceptor的安装和使用-解决把chrome浏览器登录状态同步到postman进行有依赖的接口测试   问题引入:做接口测试时,有依赖关系的接口往往不好测试( ...

  4. 解决MVC中JSON字符长度超出限制的异常

    解决MVC中JSON字符长度超出限制的异常 解决方法如下: <configuration> <system.web.extensions> <scripting> ...

  5. 解决MVC Json序列化的循环引用问题/EF Json序列化循引用问题---Newtonsoft.Json

    1..Net开源Json序列化工具Newtonsoft.Json中提供了解决序列化的循环引用问题: 方式1:指定Json序列化配置为 ReferenceLoopHandling.Ignore 方式2: ...

  6. ASP.NET MVC 用户登录Login

    ASP.NET MVC 用户登录Login一.先来看个框架例子:(这个是网上收集到的)  第一步:创建一个类库ClassLibrary831.            第二步:编写一个类实现IHttpM ...

  7. [加入用户]解决useradd 用户后没有加入用户Home文件夹的情况,Linux改变文件或文件夹的訪问权限命令,linux改动用户password,usermod的ysuum安装包。飞

    usermod的yum安装包: shadow-utils 将nobody用户加入到nogroup 组: usermod -g nogroup nobody cat /etc/passwd|grep n ...

  8. 解决Oracle用户被锁定的方法

    解决Oracle用户被锁定的方法 1,cmd控制台: 使用sqlplus 命令:sqlplus sys/密码@ip/orcl as sysdba; 2,先设置具体时间格式,以便查看具体时间 SQL&g ...

  9. ASP.NET MVC 用户权限-1

    MVC框架的开发网站的利器,MVC框架也开始越来越流行了.对于.NET ,微软也发布了MVC框架,做网站通常要涉及到用户的权限管理,对于.NET MVC 框架的用户权限管理又应该怎样设置呢?下面通过示 ...

随机推荐

  1. 在git上下载的Asp.Net MVC 4源码怎么编译?

    以本人的下载位置为例:E:\aspnetwebstack 1.win+r 输入cmd 打开dos 界面 2.e: 回车,定位到e 盘 3.cd E:\aspnetwebstack 进入e 盘aspne ...

  2. The Ninth Hunan Collegiate Programming Contest (2013) Problem I

    Problem I Interesting Calculator There is an interesting calculator. It has 3 rows of button. Row 1: ...

  3. Android开发-API指南-<intent-filter>

    <intent-filter> 英文原文:http://developer.android.com/guide/topics/manifest/intent-filter-element. ...

  4. 断言--NSAssert

    NSAssert()是一个宏,用于开发阶段调试程序中的Bug,通过为NSAssert()传递条件表达式来断定是否属于Bug,满足条件返回真值,程序继续运行,如果返回假值,则抛出异常,并切可以自定义异常 ...

  5. java基础回顾(五)——Stack、Heap

    栈(stack):是简单的数据结构,但在计算机中使用广泛.栈最显著的特征是:LIFO(Last In, First Out,后进先出).比如我们往箱子里面放衣服,先放入的在最下方,只有拿出后来放入的才 ...

  6. Unity Js与C#脚本通信

    将.js文件放到Standard Assets目录下,否则无法编译通过 CS_test.cs : using UnityEngine; using System.Collections;   publ ...

  7. Oracle 通过触发器 来创建 同步临时表 及处理 通过 自治事务 来解决 查询 基表的问题

    // 触发器 create or replace trigger tr_sync_BD_MARBASCLASS after INSERT or UPDATE on BD_MARBASCLASS for ...

  8. CAPI HTTP服务搭建(文件在本机)

    南康HTTP服务器搭建步骤如下: 1.环境准备 2.添加应用程序 3.访问测试 4.添加虚拟目录 5.下载测试 6.上传测试 7.最终效果 8.权限设置 有问题请留言.

  9. C++多态性——函数的覆盖和隐藏

    1.函数的覆盖 覆盖的条件: 基类函数必须是虚函数(使用Virtual关键字进行声明): 发生覆盖的两个函数必须分别位于派生类和基类中: 函数名称与参数列表必须完全一样: 2.函数的隐藏 隐藏,是指派 ...

  10. 第四章_PHP基本语法(2)

    1.常量的声明 在PHP中,定义常量使用define()函数来实现 2.魔术常量 名称 作用 __LINE__ 返回文件中的当前行号 __FILE__ 返回该文件的完整路径和文件名 __DIR__ 返 ...