ASP.NET MVC+EF框架+EasyUI实现权限管理系列(11)-验证码实现和底层修改
原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(11)-验证码实现和底层修改
ASP.NET MVC+EF框架+EasyUI实现权限管系列
(开篇) (1):框架搭建 (2):数据库访问层的设计Demo (3):面向接口编程 (4 ):业务逻辑层的封装
(5):前台Jquery easyUI实现 (6):EF上下文实例管理 (7):DBSession的封装 (8):DBSession线程内唯一
前言:上篇博客我们简单的说了一下源代码管理工具(VSS)的使用,相信大家看完之后都能够会使用VSS源代码管理工具,在源代码管理工具中VSS算是最简单的,没有什么难度,就是重点理解签入,签出和回滚的含有以及如何操作。那么这篇博客我们开始讲述如何实现用户的登录以及对前面博友们的评论提出修改底层的东西进行了一次修改还有验证码的使用。那么下面我首先要说的是前面网友提出的一个小的修改。
1.Func<T, bool>和Expression<Func<T, bool>>的使用区别
(1)在前面我写ASP.NET MVC+EF框架+EasyUI实现权限管理系列(4)-业务逻辑曾的封装(http://www.cnblogs.com/hanyinglong/archive/2013/04/09/3011119.html)这篇博客的时候,有一位博友(@Qlin)提出了我在项目底层些查询的时候为什么不用Expression<Func<T,bool>>,因为当时我实现的代码是Func<T,bool> wherelambda来定义的,当时的代码如下:
//实现对数据库的查询 --简单查询
IQueryable<T> LoadEntities(Func<T, bool> whereLambda); /// <summary>
/// 实现对数据的分页查询
/// </summary> /// <typeparam name="S">按照某个类进行排序</typeparam> /// <param name="pageIndex">当前第几页</param> /// <param name="pageSize">一页显示多少条数据</param> /// <param name="total">总条数</param> /// <param name="whereLambda">取得排序的条件</param> /// <param name="isAsc">如何排序,根据倒叙还是升序</param> /// <param name="orderByLambda">根据那个字段进行排序</param> /// <returns></returns> IQueryable<T> LoadPageEntities<S>(int pageIndex, int pageSize, out int total, Func<T, bool> whereLambda, bool isAsc, Func<T, S> orderByLambda);
(2)那么根据那位博友提出来的意见,我查看资料,发现他们还真的有很大的区别,这里我就简单的说一下他们的区别,并且非常感谢博友们能提出这样的问题,希望广大博友们能真心的提出来项目中的问题,我将虚心接受。
(3)那么他们有什么区别呢?网上的资料是这样说的,Func<T,bool>本身就是一个委托(delegate),而Expression<Func<T,bool>>确实一个表达式,只有在编译之后才会变成委托,那么在EF中到底使用哪一个呢?又是为什么呢?其实如果我们写成Func<T,bool>类型的便来那个如果作为参数传递给where方法进行Linq查询时,Entity FrameWork将会产生全表查询,将整个数据库表忠的数据加载到内存中,然后再内存中根据where中的条件进一步查询,而Expression<Func<t,bool>>只是查询出来你where条件中的数据,不用去进行全表查询,所以我们修改后的代码是:
//实现对数据库的查询 --简单查询 IQueryable<T> LoadEntities(Expression<Func<T, bool>> whereLambda); /// <summary> /// 实现对数据的分页查询 /// </summary> /// <typeparam name="S">按照某个类进行排序</typeparam> /// <param name="pageIndex">当前第几页</param> /// <param name="pageSize">一页显示多少条数据</param> /// <param name="total">总条数</param> /// <param name="whereLambda">取得排序的条件</param> /// <param name="isAsc">如何排序,根据倒叙还是升序</param> /// <param name="orderByLambda">根据那个字段进行排序</param> /// <returns></returns> IQueryable<T> LoadPageEntities<S>(int pageIndex, int pageSize, out int total, Expression<Func<T, bool>> whereLambda, bool isAsc, Expression<Func<T, S>> orderByLambda);
(4)上面我们简单的介绍了一下Func<T, bool>和Expression<Func<T, bool>>的使用区别,我查到了就这些资料,如果那位博友还能够详细的说明的话,真心希望你在下面留言,我将非常的感谢你们。我参考的资料是:http://www.cnblogs.com/dudu/archive/2012/04/01/enitity_framework_func.html。
(5)综上所述的话,这时候我们就要对我们项目中数据库访问层,数据库访问接口层,业务逻辑层和业务逻辑接口层的查询方法都进行修改,这里就不多说了,和上面的基本差不多。
2.登录页面的设计
(1)首先我们到网上下载一个登录页面的Demo,然后经过修改之后放到我们MVC4的项目里面。
(2)然后我们在项目中添加一个LoginController控制器,然后再在Index上面添加一个空视图,最后我们将我们前面下载的Demo中的代码部署到Index.cshtml页面之上,最后生成的静态页面如图所示:
(3)这时候我们就把静态页面设计好了,这里静态页面的代码我就不往出来贴了,在后面我会把主要的代码写出来的并且共享整个项目的,那么下来我们看到了我们的验证码没有实现,只是一个假的图标在哪里,这时候我们开始着手验证码的设计。
3.如何设计验证码的实现
(1)通过上图我们看到现在我们已经实现了页面的展示,那么我们的验证码还没有,现在开始我们设计验证码,首先看我前台验证码这里的代码是:
<ul> <li class="user_main_text">验证码: </li> <li class="user_main_input"> <input type="text" class="TxtPasswordCssClass" id="Code" name="Code"> </li> </ul> <ul> <li class="user_main_text">验证码: </li> <li class="user_main_input"> <img src="/Login/CheckCode?ID=1" id="imgCode" alt="单击可刷新" onclick="ClickRemoveChangeCode()" /> <a href="javascript:void(0)" onclick="ClickRemoveChangeCode();return false;">看不清</a> </li> </ul>
(2)首先我们看到我们绑定验证码的这里是这样写的,<img src=”/Login/CheckCode?ID=1”>,那么前面的src绑定的地址什么意思呢?他的意思就是我们在Login控制器下面含有一个CheckCode方法来实现验证码的读取。
(3)我们要实现验证码,首先我们就要写一个生成验证码的类,没什么难度,网上一搜一大推,下面就是我封装的生成验证码的类,首先我们在LYZJ.UserLimitMVC.Common类库下面新建一个KenceryValidateCode.cs类来存放生成验证码的代码,在这里我们需要给类库引入命名空间System.Drawing。最终的代码如下:
namespace LYZJ.UserLimitMVC.Common { public class KenceryValidateCode { /// <summary> /// 验证码的最大长度 /// </summary> public int MaxLength { get { return ; } } /// <summary> /// 验证码的最小长度 /// </summary> public int MinLength { get { return ; } } /// <summary> /// 生成验证码 /// </summary> /// <param name="length">指定验证码的长度</param> /// <returns></returns> public string CreateValidateCode(int length) { int[] randMembers = new int[length]; int[] validateNums = new int[length]; string validateNumberStr = ""; //生成起始序列值 int seekSeek = unchecked((int) DateTime.Now.Ticks); Random seekRand = new Random(seekSeek); int beginSeek = (int) seekRand.Next(, Int32.MaxValue - length*); int[] seeks = new int[length]; for (int i = ; i < length; i++) { beginSeek += ; seeks[i] = beginSeek; } //生成随机数字 for (int i = ; i < length; i++) { Random rand = new Random(seeks[i]); int pownum = *(int) Math.Pow(, length); randMembers[i] = rand.Next(pownum, Int32.MaxValue); } //抽取随机数字 for (int i = ; i < length; i++) { string numStr = randMembers[i].ToString(); int numLength = numStr.Length; Random rand = new Random(); int numPosition = rand.Next(, numLength - ); validateNums[i] = Int32.Parse(numStr.Substring(numPosition, )); } //生成验证码 for (int i = ; i < length; i++) { validateNumberStr += validateNums[i].ToString(); } return validateNumberStr; } //C# MVC 升级版 /// <summary> /// 创建验证码的图片 /// </summary> /// <param name="containsPage">要输出到的page对象</param> /// <param name="validateNum">验证码</param> public byte[] CreateValidateGraphic(string validateCode) { Bitmap image = new Bitmap((int) Math.Ceiling(validateCode.Length*12.0), ); Graphics g = Graphics.FromImage(image); try { //生成随机生成器 Random random = new Random(); //清空图片背景色 g.Clear(Color.White); //画图片的干扰线 for (int i = ; i < ; i++) { int x1 = random.Next(image.Width); int x2 = random.Next(image.Width); int y1 = random.Next(image.Height); int y2 = random.Next(image.Height); g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2); } Font font = new Font("Arial", , (FontStyle.Bold | FontStyle.Italic)); LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(, , image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2f, true); g.DrawString(validateCode, font, brush, , ); //画图片的前景干扰点 for (int i = ; i < ; i++) { int x = random.Next(image.Width); int y = random.Next(image.Height); image.SetPixel(x, y, Color.FromArgb(random.Next())); } //画图片的边框线 g.DrawRectangle(new Pen(Color.Silver), , , image.Width - , image.Height - ); //保存图片数据 MemoryStream stream = new MemoryStream(); image.Save(stream, ImageFormat.Jpeg); //输出图片流 return stream.ToArray(); } finally { g.Dispose(); image.Dispose(); } } /// <summary> /// 得到验证码图片的长度 /// </summary> /// <param name="validateNumLength">验证码的长度</param> /// <returns></returns> public static int GetImageWidth(int validateNumLength) { return (int) (validateNumLength*12.0); } /// <summary> /// 得到验证码的高度 /// </summary> /// <returns></returns> public static double GetImageHeight() { return 22.5; } } }
(4)那么现在我们的验证码生成的类已经完成了,这时候我们根据<img src=”/Login/CheckCode?ID=1”>所知,我们要到Login控制器下面去创建CheckCode方法来实现能够从View层读取验证码显示出来,那么必然在我们项目当中women就要用到刚才定义的获取验证码的类,那么这时候women就要添加LYZJ.UserLimitMVC.Common的引用,这时候在Login控制器下面的读取验证码的方法代码如下:
/// <summary> /// 验证码的实现 /// </summary> /// <returns></returns> public ActionResult CheckCode() { //首先实例化验证码的类 KenceryValidateCode validateCode = new KenceryValidateCode(); //生成验证码指定的长度 string code = validateCode.CreateValidateCode(); //将验证码赋值给Session变量 Session["ValidateCode"] = code; //创建验证码的图片 byte[] bytes = validateCode.CreateValidateGraphic(code); //最后将验证码返回 return File(bytes, @"image/jpeg"); }
(5)根据上面的代码,我们就实现了能够在前台显示验证码的功能,这里我就不详细的解释代码了,我在代码里面写了大量的注释,相信大家能够很容易的明白代码的意思,效果如图所示:
(6)那么这时候我们就有一个问题出现了,我们的验证码有时候可能看不清,当我们要单击”验证码本身”或者”看不清,换一张”的时候要能够动态的变化,下面我就简单介绍一下动态的变化验证码。
4.单击验证码的时候验证码随机获取
(1)当我们想要单击”验证码本身”或者”看不清,换一张”的字眼的时候我们就要实施的刷新一下验证码,那么我们看到我们在页面的HTML代码中就有一个javaScript的Clieck事件,<img src="/Login/CheckCode?ID=1" id="imgCode" alt="单击可刷新" onclick="ClickRemoveChangeCode()" /> ,最后我们只要使用JavaScript实现onClick事件的ClickRemoveChangeCode()方法,使用JavaScript实现此事件的方法如下:
@*引用Jquery文件的JS脚本*@ <script src="~/Scripts/jquery-1.7.1.min.js"></script> <script type="text/javascript"> //单击重新改变验证码 function ClickRemoveChangeCode() { //首先我们获取到验证码的路径 var code = $("#imgCode").attr("src"); //然后重新给验证码的路径赋值 $("#imgCode").attr("src", code + ""); } </script>
(2)这样我们的验证码就实现了,当然还有一些小样式的修改我就不说了,比如当鼠标移动上去的时候能够变成小手等。
(3)那么下篇博客我们将实现用户的登录,越往后面的话我会越说的简单,这些东西都不怎么难,如果大家不太清楚的话,可以留言或者加QQ群,我将很高兴为我们解决问题。
(4)最后在秀一下今天完成的验证码的功能,本来打算把登录一起写的,可是就验证码写了这么多,想想还是把登录放后面和写T4模版一起说吧。
Kencery返回本系列开篇
ASP.NET MVC+EF框架+EasyUI实现权限管理系列(11)-验证码实现和底层修改的更多相关文章
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列
http://www.cnblogs.com/hanyinglong/archive/2013/03/22/2976478.html ASP.NET MVC+EF框架+EasyUI实现权限管理系列之开 ...
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列之开篇
原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列之开篇 前言:博客又有一段时间没有更新了,心里感觉这段时间空空的,好像什么都没有学下,所以就想写博客,所以就有了这个系列,这里当然也 ...
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列(21)-用户角色权限基本的实现说明
原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(21)-用户角色权限基本的实现说明 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) (1):框 ...
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列(20)-多条件模糊查询和回收站还原的实现
原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(20)-多条件模糊查询和回收站还原的实现 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) (1):框架 ...
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列(19)-用户信息的修改和浏览
原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(19)-用户信息的修改和浏览 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) (1):框架搭建 ...
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列(18)-过滤器的使用和批量删除数据(伪删除和直接删除)
原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(18)-过滤器的使用和批量删除数据(伪删除和直接删除) ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) ...
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列(17)-注册用户功能的细节处理(各种验证)
原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(17)-注册用户功能的细节处理(各种验证) ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) (1):框 ...
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列(16)-类库架构扩展以及DLL文件生成修改和用户的简单添加
原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(16)-类库架构扩展以及DLL文件生成修改和用户的简单添加 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) ...
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列(14)-主框架搭建
原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(14)-主框架搭建 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) (1):框架搭建 (2 ...
随机推荐
- Objective-C代码块语法(block)使用
和其它变量本质上相似的代码块.所不同的是,数据存储代码块是主体的函数. 使用的代码块被,你可以像打电话一样等标准功能,传入参数的数量,并获得返回值. 插入符号(^)语法标记块.我们熟悉的参数按照规约定 ...
- 在将 varchar 值 '2,7' 转换成数据类型 int 时失败
消息 245,级别 16,状态 1,第 1 行在将 varchar 值 '2,7' 转换成数据类型 int 时失败. 原sql select UserName from s_User where ...
- 重写onBackPressed方法
android手机back按键响应方法重构: long exitTime = System.currentTimeMillis() - 2000; public void onBackPressed( ...
- Linux 没有 my.cnf 解决方案文件完全我自己的整个教程很多口才
我看过好多关于Linux下没有my.cnf的博客,都是什么rmp安装没有my.cnf文件啊,然后什么两个方法啊,我就无语了,大家要是知道就不会查资料了,你们敢不敢负责点?说具体点?有的说从 /usr/ ...
- 引用第三方框架 不支持ARC
我们会常常遇到一个问题就是引用第三方框架之后发现不支持内存的自己主动处理(ARC) 我们须要这样来操作: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdT ...
- 《TCP/IP详细解释》札记(23章)-TCP该保活定时器
可能有这样的备用现实TCP连接:流通过. 也就是说.假设TCP连接的两方都没有向对方发送数据.则在两个TCP模块之间不交换不论什么信息,这意味着我们能够启动一个客户与server建立连接,然后长时间不 ...
- 在Ceph创建虚拟机的过程改进分析
作为个人学习笔记分享.有不论什么问题欢迎交流! 近期在Gerrit中看到一个change:https://review.openstack.org/#/c/94295/ , 它主要是对当前在Ceph中 ...
- jxl创Excel档java示例代码说明
记得下载 并 导入jxl.jar 包,免积分下载地址:http://download.csdn.net/detail/u010011052/7561041 package Test; import j ...
- Struts2 拦截器—拦截action
对于拦截器的基本使用这里我就懒得打字了,我这里就讲下如何用 Struts2 拦截器 拦截action.这是我个人的想法,如果有什么不对的,或者你们有什么更好的方法.请多多留言! 拦截器的默认拦截的方法 ...
- 但从谈论性能点SQL Server选择聚集索引键
简单介绍 在SQL Server中,数据是按页进行存放的.而为表加上聚集索引后,SQL Server对于数据的查找就是依照聚集索引的列作为keyword进行了. 因此对于聚集索引的选择对性能的影响就变 ...