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线程内唯一  

   (9):TT摸版的学习   (10):VSS源代码管理

  前言:上篇博客我们简单的说了一下源代码管理工具(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来定义的,当时的代码如下:

 1         //实现对数据库的查询  --简单查询

 2         IQueryable<T> LoadEntities(Func<T, bool> whereLambda);

 3 

 4         /// <summary>

 5         /// 实现对数据的分页查询

 6         /// </summary>

 7 

 8         /// <typeparam name="S">按照某个类进行排序</typeparam>

 9 

10         /// <param name="pageIndex">当前第几页</param>

11 

12         /// <param name="pageSize">一页显示多少条数据</param>

13 

14         /// <param name="total">总条数</param>

15 

16         /// <param name="whereLambda">取得排序的条件</param>

17 

18         /// <param name="isAsc">如何排序,根据倒叙还是升序</param>

19 

20         /// <param name="orderByLambda">根据那个字段进行排序</param>

21 

22         /// <returns></returns>

23 

24         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条件中的数据,不用去进行全表查询,所以我们修改后的代码是:   

 1  //实现对数据库的查询  --简单查询

 2 

 3         IQueryable<T> LoadEntities(Expression<Func<T, bool>> whereLambda);

 4 

 5         /// <summary>

 6 

 7         /// 实现对数据的分页查询

 8 

 9         /// </summary>

10 

11         /// <typeparam name="S">按照某个类进行排序</typeparam>

12 

13         /// <param name="pageIndex">当前第几页</param>

14 

15         /// <param name="pageSize">一页显示多少条数据</param>

16 

17         /// <param name="total">总条数</param>

18 

19         /// <param name="whereLambda">取得排序的条件</param>

20 

21         /// <param name="isAsc">如何排序,根据倒叙还是升序</param>

22 

23         /// <param name="orderByLambda">根据那个字段进行排序</param>

24 

25         /// <returns></returns>

26 

27         IQueryable<T> LoadPageEntities<S>(int pageIndex, int pageSize, out int total, Expression<Func<T, bool>> whereLambda,

28 

29                                           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页面之上,最后生成的静态页面如图所示:

   ASP.NET MVC+EF框架+EasyUI实现权限管理系列(11)-验证码实现和底层修改

  (3)这时候我们就把静态页面设计好了,这里静态页面的代码我就不往出来贴了,在后面我会把主要的代码写出来的并且共享整个项目的,那么下来我们看到了我们的验证码没有实现,只是一个假的图标在哪里,这时候我们开始着手验证码的设计。

3.如何设计验证码的实现

  (1)通过上图我们看到现在我们已经实现了页面的展示,那么我们的验证码还没有,现在开始我们设计验证码,首先看我前台验证码这里的代码是:

 1 <ul>

 2 

 3    <li class="user_main_text">验证码: </li>

 4 

 5    <li class="user_main_input">

 6 

 7        <input type="text" class="TxtPasswordCssClass" id="Code" name="Code">

 8 

 9    </li>

10 

11 </ul>

12 

13 <ul>

14 

15    <li class="user_main_text">验证码: </li>

16 

17    <li class="user_main_input">

18 

19 <img src="/Login/CheckCode?ID=1" id="imgCode" alt="单击可刷新" onclick="ClickRemoveChangeCode()"  />

20 

21 <a href="javascript:void(0)" onclick="ClickRemoveChangeCode();return false;">看不清</a>

22 

23     </li>

24 

25 </ul>

  (2)首先我们看到我们绑定验证码的这里是这样写的,<img src=”/Login/CheckCode?ID=1”>,那么前面的src绑定的地址什么意思呢?他的意思就是我们在Login控制器下面含有一个CheckCode方法来实现验证码的读取。

  (3)我们要实现验证码,首先我们就要写一个生成验证码的类,没什么难度,网上一搜一大推,下面就是我封装的生成验证码的类,首先我们在LYZJ.UserLimitMVC.Common类库下面新建一个KenceryValidateCode.cs类来存放生成验证码的代码,在这里我们需要给类库引入命名空间System.Drawing。最终的代码如下:

  1 namespace LYZJ.UserLimitMVC.Common

  2 

  3 {

  4 

  5     public class KenceryValidateCode

  6 

  7     {

  8 

  9         /// <summary>

 10 

 11         /// 验证码的最大长度

 12 

 13         /// </summary>

 14 

 15         public int MaxLength

 16 

 17         {

 18 

 19             get { return 10; }

 20 

 21         }

 22 

 23  

 24 

 25         /// <summary>

 26 

 27         /// 验证码的最小长度

 28 

 29         /// </summary>

 30 

 31         public int MinLength

 32 

 33         {

 34 

 35             get { return 1; }

 36 

 37         }

 38 

 39  

 40 

 41         /// <summary>

 42 

 43         /// 生成验证码

 44 

 45         /// </summary>

 46 

 47         /// <param name="length">指定验证码的长度</param>

 48 

 49         /// <returns></returns>

 50 

 51         public string CreateValidateCode(int length)

 52 

 53         {

 54 

 55             int[] randMembers = new int[length];

 56 

 57             int[] validateNums = new int[length];

 58 

 59             string validateNumberStr = "";

 60 

 61             //生成起始序列值

 62 

 63             int seekSeek = unchecked((int) DateTime.Now.Ticks);

 64 

 65             Random seekRand = new Random(seekSeek);

 66 

 67             int beginSeek = (int) seekRand.Next(0, Int32.MaxValue - length*10000);

 68 

 69             int[] seeks = new int[length];

 70 

 71             for (int i = 0; i < length; i++)

 72 

 73             {

 74 

 75                 beginSeek += 10000;

 76 

 77                 seeks[i] = beginSeek;

 78 

 79             }

 80 

 81             //生成随机数字

 82 

 83             for (int i = 0; i < length; i++)

 84 

 85             {

 86 

 87                 Random rand = new Random(seeks[i]);

 88 

 89                 int pownum = 1*(int) Math.Pow(10, length);

 90 

 91                 randMembers[i] = rand.Next(pownum, Int32.MaxValue);

 92 

 93             }

 94 

 95             //抽取随机数字

 96 

 97             for (int i = 0; i < length; i++)

 98 

 99             {

100 

101                 string numStr = randMembers[i].ToString();

102 

103                 int numLength = numStr.Length;

104 

105                 Random rand = new Random();

106 

107                 int numPosition = rand.Next(0, numLength - 1);

108 

109                 validateNums[i] = Int32.Parse(numStr.Substring(numPosition, 1));

110 

111             }

112 

113             //生成验证码

114 

115             for (int i = 0; i < length; i++)

116 

117             {

118 

119                 validateNumberStr += validateNums[i].ToString();

120 

121             }

122 

123             return validateNumberStr;

124 

125         }

126 

127  

128 

129         //C# MVC 升级版

130 

131         /// <summary>

132 

133         /// 创建验证码的图片

134 

135         /// </summary>

136 

137         /// <param name="containsPage">要输出到的page对象</param>

138 

139         /// <param name="validateNum">验证码</param>

140 

141         public byte[] CreateValidateGraphic(string validateCode)

142 

143         {

144 

145             Bitmap image = new Bitmap((int) Math.Ceiling(validateCode.Length*12.0), 22);

146 

147             Graphics g = Graphics.FromImage(image);

148 

149             try

150 

151             {

152 

153                 //生成随机生成器

154 

155                 Random random = new Random();

156 

157                 //清空图片背景色

158 

159                 g.Clear(Color.White);

160 

161                 //画图片的干扰线

162 

163                 for (int i = 0; i < 25; i++)

164 

165                 {

166 

167                     int x1 = random.Next(image.Width);

168 

169                     int x2 = random.Next(image.Width);

170 

171                     int y1 = random.Next(image.Height);

172 

173                     int y2 = random.Next(image.Height);

174 

175                     g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);

176 

177                 }

178 

179                 Font font = new Font("Arial", 12, (FontStyle.Bold | FontStyle.Italic));

180 

181                 LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height),

182 

183                                                                     Color.Blue, Color.DarkRed, 1.2f, true);

184 

185                 g.DrawString(validateCode, font, brush, 3, 2);

186 

187                 //画图片的前景干扰点

188 

189                 for (int i = 0; i < 100; i++)

190 

191                 {

192 

193                     int x = random.Next(image.Width);

194 

195                     int y = random.Next(image.Height);

196 

197                     image.SetPixel(x, y, Color.FromArgb(random.Next()));

198 

199                 }

200 

201                 //画图片的边框线

202 

203                 g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);

204 

205                 //保存图片数据

206 

207                 MemoryStream stream = new MemoryStream();

208 

209                 image.Save(stream, ImageFormat.Jpeg);

210 

211                 //输出图片流

212 

213                 return stream.ToArray();

214 

215             }

216 

217             finally

218 

219             {

220 

221                 g.Dispose();

222 

223                 image.Dispose();

224 

225             }

226 

227         }

228 

229  

230 

231         /// <summary>

232 

233         /// 得到验证码图片的长度

234 

235         /// </summary>

236 

237         /// <param name="validateNumLength">验证码的长度</param>

238 

239         /// <returns></returns>

240 

241         public static int GetImageWidth(int validateNumLength)

242 

243         {

244 

245             return (int) (validateNumLength*12.0);

246 

247         }

248 

249  

250 

251         /// <summary>

252 

253         /// 得到验证码的高度

254 

255         /// </summary>

256 

257         /// <returns></returns>

258 

259         public static double GetImageHeight()

260 

261         {

262 

263             return 22.5;

264 

265         }

266 

267     }

268 

269 }

  (4)那么现在我们的验证码生成的类已经完成了,这时候我们根据<img src=”/Login/CheckCode?ID=1”>所知,我们要到Login控制器下面去创建CheckCode方法来实现能够从View层读取验证码显示出来,那么必然在我们项目当中women就要用到刚才定义的获取验证码的类,那么这时候women就要添加LYZJ.UserLimitMVC.Common的引用,这时候在Login控制器下面的读取验证码的方法代码如下:

 1        /// <summary>

 2 

 3         /// 验证码的实现

 4 

 5         /// </summary>

 6 

 7         /// <returns></returns>

 8 

 9         public ActionResult CheckCode()

10 

11         {

12 

13             //首先实例化验证码的类

14 

15             KenceryValidateCode validateCode = new KenceryValidateCode();

16 

17             //生成验证码指定的长度

18 

19             string code = validateCode.CreateValidateCode(5);

20 

21             //将验证码赋值给Session变量

22 

23             Session["ValidateCode"] = code;

24 

25             //创建验证码的图片

26 

27             byte[] bytes = validateCode.CreateValidateGraphic(code);

28 

29             //最后将验证码返回

30 

31             return File(bytes, @"image/jpeg");

32 

33         }

  (5)根据上面的代码,我们就实现了能够在前台显示验证码的功能,这里我就不详细的解释代码了,我在代码里面写了大量的注释,相信大家能够很容易的明白代码的意思,效果如图所示:

         ASP.NET MVC+EF框架+EasyUI实现权限管理系列(11)-验证码实现和底层修改

  (6)那么这时候我们就有一个问题出现了,我们的验证码有时候可能看不清,当我们要单击”验证码本身”或者”看不清,换一张”的时候要能够动态的变化,下面我就简单介绍一下动态的变化验证码。

4.单击验证码的时候验证码随机获取

  (1)当我们想要单击”验证码本身”或者”看不清,换一张”的字眼的时候我们就要实施的刷新一下验证码,那么我们看到我们在页面的HTML代码中就有一个javaScript的Clieck事件,<img src="/Login/CheckCode?ID=1" id="imgCode" alt="单击可刷新" onclick="ClickRemoveChangeCode()"  /> ,最后我们只要使用JavaScript实现onClick事件的ClickRemoveChangeCode()方法,使用JavaScript实现此事件的方法如下:

 1      @*引用Jquery文件的JS脚本*@

 2 

 3         <script src="~/Scripts/jquery-1.7.1.min.js"></script>

 4 

 5         <script type="text/javascript">

 6 

 7             //单击重新改变验证码

 8 

 9             function ClickRemoveChangeCode() {

10 

11                 //首先我们获取到验证码的路径

12 

13                 var code = $("#imgCode").attr("src");

14 

15                 //然后重新给验证码的路径赋值

16 

17                 $("#imgCode").attr("src", code + "1");

18 

19             }

20 

21         </script>

  (2)这样我们的验证码就实现了,当然还有一些小样式的修改我就不说了,比如当鼠标移动上去的时候能够变成小手等。

  (3)那么下篇博客我们将实现用户的登录,越往后面的话我会越说的简单,这些东西都不怎么难,如果大家不太清楚的话,可以留言或者加QQ群,我将很高兴为我们解决问题。

  (4)最后在秀一下今天完成的验证码的功能,本来打算把登录一起写的,可是就验证码写了这么多,想想还是把登录放后面和写T4模版一起说吧。

     ASP.NET MVC+EF框架+EasyUI实现权限管理系列(11)-验证码实现和底层修改

  

  Kencery返回本系列开篇

  

你可能感兴趣的:(asp.net)