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頁面之上,最后生成的靜態頁面如圖所示:

   

  (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)根據上面的代碼,我們就實現了能夠在前台顯示驗證碼的功能,這里我就不詳細的解釋代碼了,我在代碼里面寫了大量的注釋,相信大家能夠很容易的明白代碼的意思,效果如圖所示:

         

  (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模版一起說吧。

     

 

源碼下載

 

 

 

   (1):完整源碼下載

 

  Kencery返回本系列開篇

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM