MVC查詢數據接收及校驗

原本想寫一篇aspx的TreeView控件綁值的文章的,在寫案例的時候,寫了一半,發現有些地方還得考慮如下,就留待下次了。sql

這一篇的話,是最近在開發一個項目的時候,有大量的頁面和數據表,須要花式查詢,數據庫

後臺接收前臺傳遞過來的數據的時候,被虐的欲仙欲死,大量的校驗和重複代碼,ide

後來找到了一種很是不錯的方法,分享出來,下面是正文。。。。。學習

 

使用過MVC的人都知道,它有一個很是方便的功能,就是自動綁值,先來一個最簡單的:spa

1         public ActionResult Index(string userName, int type) {
2             /*
3              代碼塊
4              */
5             return View();
6         }    

當從前臺傳遞過來的數據中,有兩個參數名字爲userName或type時,MVC會自動幫咱們將參數類型轉好,值給好。.net

咱們要作的無非是直接使用罷了,可是,當要傳遞的值很是多的時候,不管是寫仍是看,都會很是吃力,好比這樣:code

1         public ActionResult Index01(string userName, int type, string code, int height, string sex, DateTime startTime, DateTime endTime) {
2             /*
3              代碼塊
4              */
5             return View();
6         }

其實,七個查詢參數並很少,當參數數量達到十個,二十個時,相信我,你會炸的,orm

通常這個時候,咱們可用選擇使用對象,就像這樣:對象

 1         public ActionResult Index01(User user) {
 2             /*
 3              代碼塊
 4              */
 5             return View();
 6         }
 7 
 8     /// <summary>
 9     /// 用戶類
10     /// </summary>
11     public class User {
12 
13         /// <summary>
14         /// 用戶姓名
15         /// </summary>
16         public string userName;
17 
18         /// <summary>
19         /// 用戶類型
20         /// </summary>
21         public int type;
22 
23         /// <summary>
24         /// 身份證號
25         /// </summary>
26         public string code;
27 
28         /// <summary>
29         /// 用戶身高
30         /// </summary>
31         public int height;
32 
33         /// <summary>
34         /// 用戶性別
35         /// </summary>
36         public string sex;
37 
38         #region 註冊時間範圍
39 
40         public DateTime startTime;
41         public DateTime endTime;
42 
43         #endregion
44 
45     }

這樣寫是否是看起來舒服了不少?MVC一樣可以幫你將數據依次綁好,同時,代碼的複用率也會提升不少,blog

如今解決了數據接收的問題,接下來的,就是數據的校驗了。

==========分隔符==========

拿到參數後,咱們是不能馬上去使用的,須要對參數進行一次校驗,校驗的目的,就是防止有人惡意傳遞錯誤數據給後臺,

若不進行數據校驗的話,很容易致使項目崩潰,或者數據丟失等等一系列問題,簡單的說一些校驗類型吧,

string 變量,主要校驗是否包含sql注入字符,而後判斷是否爲null,還要去掉多餘的空格

int 變量,主要檢驗是否在某一個範圍內,以及默認值是0仍是-1,或者是其它的一些數字

DateTime 變量,通常都是兩個一塊兒使用,一個開始一個結束,這個時候咱們就要校驗,開始時間是否小於或等於結束時間,以及結束時間是否小於或等於當前時間,

還有一點值得注意的是,若開始時間和結束時間精確到天時,如果同一天,在數據庫是沒法查出數據的,因此必須精確到秒

 

咱們按這個思路去添加校驗:

        public ActionResult Index01(User user) {

            // 字符串校驗
            // 判斷是否爲空爲null
            if (string.IsNullOrEmpty(user.userName))
                user.userName = user.userName.Trim();// 去掉多餘空格
            // SQL注入校驗
            if (CheckSQL(user.userName))
                user.userName = "";// 替換掉帶有SQL注入的字符

            // 數字校驗
            if (user.type < 0 || 20 < user.type)
                user.type = 0;// 當範圍不在[0,20]時,給默認值0

            // 時間校驗
            /*
              沒有六七十行搞不定,就不寫了,,,
             */

            return View();
        }

看起來仍是不錯的,但若是考慮到,每一個數據的範圍不同,校驗也是各不相同,並且,一個數據校驗最少就得寫兩行代碼,

當參數多了的時候,光校驗代碼都得寫上一兩百行,能夠想一想,若是有一百個相似的頁面,呵呵。。。

不只僅是看的難受,維護也是至關困難的,

因此我就想,能不能前臺向後臺請求的數據,都用一個類來接收,全部的校驗都寫在這個類裏面,

類的每一個參數,在輸出的時候,都進行校驗,這樣可用極大的省略,接收數據以後在視圖中的校驗,而是將校驗放在一塊兒,

同時,相同校驗方法的的參數,可用限制參數名爲同一個,代碼的複用率也會獲得提高,對於維護和修改也能輕鬆進行,,,

 

說幹就幹,當時寫出來的類,通過這麼久的修改和添加,已經能夠拿出來溜溜了,先上使用代碼吧:

 1         public ActionResult Index01(ReqData data) {
 2 
 3             string sqlstr = string.Format(" select * from dt_user where userName='{0}' ", data.UserName);
 4 
 5             /*
 6              執行sql語句,以及其餘操做,,,
 7              */
 8 
 9             return View();
10         }

有沒有瞬間感受畫風不對,說好的校驗哪去了?怎麼能直接使用??

其實,全部的校驗都在ReqData這個類裏面,能夠在它裏面添加本身須要的參數,以及對應的校驗方法,這樣,使用的時候就會很是簡單了

我主要想要分享的是一種封裝的思想和技巧,可能ReqData這個類仍是很簡陋,但仍是但願能對你們有所幫助,好像有點長,貼上代碼先:

 

  1 using System;
  2 
  3 namespace Demo.Model {
  4 
  5     /// <summary>
  6     /// 用於接收前臺傳過來的數據
  7     /// </summary>
  8     public struct ReqData {
  9 
 10         #region 分頁數據
 11 
 12         /// <summary>
 13         /// 數據總行數
 14         /// </summary>
 15         public int PageCount { get; set; }
 16 
 17         /// <summary>
 18         /// 當前頁碼
 19         /// </summary>
 20         public int PageIndex {
 21             get {
 22                 if (pageIndex == 0)
 23                     pageIndex = 1;
 24                 return pageIndex;
 25             }
 26             set {
 27                 pageIndex = value;
 28             }
 29         }
 30         private int pageIndex;
 31 
 32         /// <summary>
 33         /// 每頁行數
 34         /// </summary>
 35         public int PageSize {
 36             get {
 37                 if (pageSize == 0)
 38                     pageSize = 10;
 39                 return pageSize;
 40             }
 41             set {
 42                 pageSize = value;
 43             }
 44         }
 45         private int pageSize;
 46 
 47         /// <summary>
 48         /// 頁面跳轉連接,帶參數
 49         /// 用於分頁跳轉
 50         /// </summary>
 51         public string PageUrl { get; set; }
 52 
 53         /// <summary>
 54         /// 頁面跳轉連接,不帶參數
 55         /// 用於刪除時跳轉
 56         /// </summary>
 57         public string GetPageUrl {
 58             get {
 59                 // 判斷是否爲空
 60                 if (PageUrl == null)
 61                     return "";
 62 
 63                 // 檢測是否有參數
 64                 int index = PageUrl.LastIndexOf("?");
 65                 // 去掉參數
 66                 if (index > 0)
 67                     return PageUrl.Substring(0, index);
 68                 return PageUrl;
 69             }
 70         }
 71 
 72         #endregion
 73 
 74         #region 頁面參數
 75 
 76         /// <summary>
 77         /// 視圖樣式,{ txt:列表視圖,img:圖片視圖 }
 78         /// </summary>
 79         public string Show {
 80             get {
 81                 CheckStr(ref show);
 82 
 83                 if (string.IsNullOrEmpty(show))
 84                     show = "txt";
 85                 if (show != "txt" && show != "img")
 86                     show = "txt";
 87                 return show;
 88             }
 89             set { show = value; }
 90         }
 91         private string show;
 92 
 93         /// <summary>
 94         /// 導航欄標題
 95         /// </summary>
 96         public string Title {
 97             get { return CheckStr(ref title); }
 98             set { title = value; }
 99         }
100         private string title;
101 
102         #endregion
103 
104         #region 查詢參數
105 
106         /// <summary>
107         /// 用戶編號
108         /// </summary>
109         public int? ID {
110             get { return id; }
111             set { id = value; }
112         }
113         private int? id;
114 
115         /// <summary>
116         /// 用戶名
117         /// </summary>  
118         public string UserName {
119             get { return CheckStr(ref userName); }
120             set { userName = value; }
121         }
122         private string userName;
123 
124         /// <summary>
125         /// 用戶等級,範圍:[0,3]
126         /// </summary>
127         public int? Leavel {
128             get { return GetNumInMinToMax(ref leavel, 0, 3); }
129             set { leavel = value; }
130         }
131         private int? leavel;
132         
133         #region 時間參數
134 
135         #region 時間接收
136         
137         private DateTime? start_Time;
138         /// <summary>
139         /// 開始時間,時分秒爲 0:0:0,而且不能大於End_Time
140         /// </summary>
141         public DateTime? Start_Time {
142             get {
143                 // 容許開始時間爲空
144                 if (start_Time == null)
145                     return start_Time;
146 
147                 // 若開始時間大於當前時間
148                 if (start_Time.Value > DateTime.Now)
149                     // 開始時間爲當前時間
150                     start_Time = DateTime.Now;
151 
152                 // 當結束時間不爲空
153                 if (end_Time != null)
154                     // 當開始時間大於結束時間時
155                     if (start_Time > End_Time)
156                         // 取結束時間當天的凌晨
157                         start_Time = new DateTime(End_Time.Value.Year, End_Time.Value.Month, End_Time.Value.Day, 0, 0, 0);
158 
159                 return start_Time;
160             }
161             set { start_Time = value; }
162         }
163 
164         private DateTime? end_Time;
165         /// <summary>
166         /// 結束時間,時分秒爲 23:59:59,而且不能大於當前時間
167         /// </summary>
168         public DateTime? End_Time {
169             get {
170                 // 容許結束時間爲空
171                 if (end_Time == null)
172                     return end_Time;
173 
174                 // 若結束時間大於當前時間
175                 if (end_Time.Value >= DateTime.Now)
176                     // 結束時間爲當前時間
177                     end_Time = DateTime.Now;
178                 else {
179                     // 獲取結束時間的信息
180                     int year = end_Time.Value.Year;
181                     int month = end_Time.Value.Month;
182                     int day = end_Time.Value.Day;
183 
184                     int hour = end_Time.Value.Hour;
185                     int minute = end_Time.Value.Minute;
186                     int second = end_Time.Value.Second;
187 
188                     // 當時分秒均爲0時,爲結束時間加上時分秒
189                     if (hour == 0 && minute == 0 && second == 0) {
190                         DateTime now = DateTime.Now;
191                         // 若結束時間的年月日正好是當天
192                         if (now.Year == year && now.Month == month && now.Day == day)
193                             end_Time = now;
194                         // 不然,給到結束時間那天,最後一秒
195                         else
196                             end_Time = new DateTime(year, month, day, 23, 59, 59);
197                     }
198                 }
199 
200                 return end_Time;
201             }
202             set { end_Time = value; }
203         }
204 
205         #endregion
206 
207         #region 時間輸出
208 
209         /// <summary>
210         /// 時間字符串返回格式
211         /// 若不設置,默認爲"yyyy-MM-dd HH:mm:ss"
212         /// </summary>
213         public string Format {
214             get {
215                 if (format == null)
216                     format = "yyyy-MM-dd HH:mm:ss";
217                 return format;
218             }
219             set { format = value; }
220         }
221         private string format;
222 
223         /// <summary>
224         /// 用於返回開始時間字符串
225         /// </summary>
226         public string GetStarTimeStr {
227             get {
228                 if (Start_Time.HasValue)
229                     return Start_Time.Value.ToString(Format);
230                 return "";
231             }
232         }
233 
234         /// <summary>
235         /// 用於返回結束時間字符串
236         /// </summary>
237         public string GetEndTimeStr {
238             get {
239                 if (End_Time.HasValue)
240                     return End_Time.Value.ToString(Format);
241                 return "";
242             }
243         }
244 
245         #endregion
246 
247         #endregion
248 
249         #endregion
250 
251         #region 校驗方法
252 
253         /// <summary>
254         /// 保證num的值範圍爲,[min,max]
255         /// </summary>
256         /// <param name="num">原始數據</param>
257         /// <param name="min">最小值</param>
258         /// <param name="max">最大值</param>
259         /// <param name="def">默認值(不填時,默認值爲最小值)</param>
260         /// <returns></returns>
261         public int? GetNumInMinToMax(ref int? num, int min, int max, int? def = null) {
262             // 若def沒有值,將最小值給它
263             if (!def.HasValue)
264                 def = min;
265             // 若num沒有值,將默認值給它
266             if (!num.HasValue)
267                 num = def;
268             // 若num的值小於最小值,或大於最大值,將默認值給它
269             else if (num < min || max < num)
270                 num = def;
271 
272             return num;
273         }
274 
275         /// <summary>
276         /// 將字符串去掉空格,並進行敏感字符檢測
277         /// </summary>
278         /// <param name="str">原字符串</param>
279         /// <param name="Ischeck">是否開啓敏感字符校驗</param>
280         /// <param name="def">默認的值,字符串爲空時,賦此值</param>
281         /// <returns></returns>
282         public string CheckStr(ref string str, bool Ischeck = true,string def="") {
283             if (string.IsNullOrEmpty(str))
284                 return str = def;
285             str = str.Trim();
286             if (Ischeck)
287                 if (!GetIsFormText(str))
288                     str = "請不要輸入敏感字符!";
289             return str;
290         }
291 
292         /// <summary>
293         /// 檢測是否含有危險字符(防止Sql注入)
294         /// 轉自:http://blog.csdn.net/chaozi/article/details/4462312
295         /// </summary>
296         /// <param name="contents">預檢測的內容</param>
297         /// <returns>返回True或false</returns>
298         public static bool GetIsFormText(string contents) {
299             bool bReturnValue = false;
300             if (contents.Length > 0) {
301                 //convert to lower
302                 string sLowerStr = contents.ToLower();
303                 //RegularExpressions
304                 string sRxStr = "(/sand/s)|(/sand/s)|(/slike/s)|(select/s)|(insert/s)|" +
305                     "(delete/s)|(update/s[/s/S].*/sset)|(create/s)|(/stable)|(<[iframe|/iframe|" +
306                     "script|/script])|(')|(/sexec)|(/sdeclare)|(/struncate)|(/smaster)|(/sbackup)|(/smid)|(/scount)";
307                 //Match
308                 bool bIsMatch = false;
309                 System.Text.RegularExpressions.Regex sRx = new
310 
311                 System.Text.RegularExpressions.Regex(sRxStr);
312                 bIsMatch = sRx.IsMatch(sLowerStr, 0);
313                 if (bIsMatch) {
314                     bReturnValue = true;
315                 }
316             }
317             return bReturnValue;
318         }
319 
320         #endregion
321 
322         #region 數據綁定方法
323 
324         /// <summary>
325         /// 返回指定區間的日期,默認今天
326         /// </summary>
327         /// <param name="dateSection"></param>
328         public void GetDateSection(DateSection dateSection = DateSection.Today) {
329 
330             // 判斷枚舉中,是否存在此項
331             if (!Enum.IsDefined(typeof(DateSection), (int)dateSection))
332                 dateSection = DateSection.Today;
333 
334             // 日期
335             DateTime Date = DateTime.Now;
336 
337             // 倒退的天數
338             int BackDay = 0;
339 
340             switch (dateSection) {
341 
342                 #region =====今天=====
343 
344                 case DateSection.Today:
345                     End_Time = Date;
346                     Start_Time = new DateTime(Date.Year, Date.Month, Date.Day, 0, 0, 0, 0);
347                     break;
348 
349                 #endregion
350 
351                 #region =====昨天=====
352 
353                 case DateSection.Yesterday:
354                     Date = DateTime.Now.AddDays(-1);
355 
356                     End_Time = new DateTime(Date.Year, Date.Month, Date.Day, 23, 59, 59, 999);
357                     Start_Time = new DateTime(Date.Year, Date.Month, Date.Day, 0, 0, 0, 0, 0);
358                     break;
359 
360                 #endregion
361 
362                 #region =====本週=====
363 
364                 case DateSection.ThisWeek:
365                     End_Time = Date;
366 
367                     // 獲取今天是本週第幾天
368                     BackDay = Convert.ToInt32(Date.DayOfWeek.ToString("d"));
369 
370                     Date = DateTime.Now.AddDays(-BackDay);
371                     Start_Time = new DateTime(Date.Year, Date.Month, Date.Day, 0, 0, 0, 0);
372                     break;
373 
374                 #endregion
375 
376                 #region =====上週=====
377 
378                 case DateSection.LastWeek:
379                     BackDay = Convert.ToInt32(Date.DayOfWeek.ToString("d")) + 1;
380 
381                     // 到上週最後一天
382                     Date = DateTime.Now.AddDays(-BackDay);
383                     End_Time = new DateTime(Date.Year, Date.Month, Date.Day, 23, 59, 59, 999);
384 
385                     // 到上週第一天
386                     Date = Date.AddDays(-6);
387                     Start_Time = new DateTime(Date.Year, Date.Month, Date.Day, 0, 0, 0, 0);
388 
389                     break;
390 
391                 #endregion
392 
393                 #region =====本月=====
394 
395                 case DateSection.ThisMonth:
396                     End_Time = Date;
397                     Start_Time = new DateTime(Date.Year, Date.Month, 1, 0, 0, 0, 0);
398                     break;
399 
400                 #endregion
401 
402                 #region =====上月=====
403 
404                 case DateSection.LastMonth:
405 
406                     BackDay = Date.Day;
407 
408                     // 到上月最後一天
409                     Date = DateTime.Now.AddDays(-BackDay);
410                     End_Time = new DateTime(Date.Year, Date.Month, Date.Day, 23, 59, 59, 999);
411 
412                     Start_Time = new DateTime(Date.Year, Date.Month, 1, 0, 0, 0, 0);
413                     break;
414 
415                 #endregion
416 
417                 #region =====今年=====
418 
419                 case DateSection.ThisYear:
420                     End_Time = Date;
421                     Start_Time = new DateTime(Date.Year, 1, 1, 0, 0, 0, 0);
422                     break;
423 
424                 #endregion
425 
426                 #region =====去年=====
427 
428                 case DateSection.LastYear:
429                     BackDay = Date.DayOfYear;
430 
431                     // 到去年最後一天
432                     Date = DateTime.Now.AddDays(-BackDay);
433                     End_Time = new DateTime(Date.Year, Date.Month, Date.Day, 23, 59, 59, 999);
434 
435                     Start_Time = new DateTime(Date.Year, 1, 1, 0, 0, 0, 0);
436                     break;
437 
438                 #endregion
439 
440                 default: break;
441             }
442 
443         }
444 
445         /// <summary>
446         /// 保證開始和結束時間絕對不爲空
447         /// </summary>
448         /// <param name="DateLong">間隔長度,默認:7</param>
449         /// <param name="dateFormat">間隔單位,默認:Day(天)</param>
450         public void GetDateNow(int DateLong = 7, DateFormat dateFormat = DateFormat.Day) {
451 
452             // 校驗是否存在此枚舉
453             if (Enum.IsDefined(typeof(DateFormat), (int)dateFormat))
454                 dateFormat = DateFormat.Day;
455 
456             // 初始化結束時間
457             if (End_Time == null)
458                 End_Time = DateTime.Now;
459 
460             DateTime? star;
461 
462             // 有校驗的時間
463             star = new DateTime();
464             star = Start_Time;
465             ChangStar(ref star, End_Time, DateLong, dateFormat);
466             Start_Time = star;
467 
468         }
469 
470         /// <summary>
471         /// 根據結束時間,修改開始時間
472         /// 若開始時間有值,則不改動
473         /// </summary>
474         /// <param name="Start">開始時間</param>
475         /// <param name="End">結束時間</param>
476         /// <param name="DateLong">間隔長度</param>
477         /// <param name="dateFormat">間隔單位</param>
478         private void ChangStar(ref DateTime? Start, DateTime? End, int DateLong, DateFormat dateFormat) {
479 
480             if (Start.HasValue)
481                 return;
482 
483             DateLong = 0 - DateLong;
484 
485             // 獲取開始時間
486             switch (dateFormat) {
487                 // 年份
488                 case DateFormat.Year:
489                     Start = End.Value.AddYears(DateLong);
490                     break;
491                 // 月份
492                 case DateFormat.Month:
493                     Start = End.Value.AddMonths(DateLong);
494                     break;
495                 // 天數
496                 case DateFormat.Day:
497                     Start = End.Value.AddDays(DateLong);
498                     break;
499                 // 小時
500                 case DateFormat.Hour:
501                     Start = End.Value.AddHours(DateLong);
502                     break;
503                 // 分鐘
504                 case DateFormat.Minute:
505                     Start = End.Value.AddMinutes(DateLong);
506                     break;
507                 // 秒鐘
508                 case DateFormat.Second:
509                     Start = End.Value.AddSeconds(DateLong);
510                     break;
511             }
512 
513         }
514 
515         #endregion
516     }
517 
518     /// <summary>
519     /// 時間格式
520     /// </summary>
521     public enum DateFormat {
522         /// <summary>
523         /// 年份
524         /// </summary>
525         Year,
526         /// <summary>
527         /// 月份
528         /// </summary>
529         Month,
530         /// <summary>
531         /// 天數
532         /// </summary>
533         Day,
534         /// <summary>
535         /// 小時
536         /// </summary>
537         Hour,
538         /// <summary>
539         /// 分鐘
540         /// </summary>
541         Minute,
542         /// <summary>
543         /// 秒鐘
544         /// </summary>
545         Second
546     }
547 
548     /// <summary>
549     /// 時間區間
550     /// </summary>
551     public enum DateSection {
552         /// <summary>
553         /// 今天
554         /// </summary>
555         Today,
556         /// <summary>
557         /// 昨天
558         /// </summary>
559         Yesterday,
560         /// <summary>
561         /// 本週,星期天爲第一天
562         /// </summary>
563         ThisWeek,
564         /// <summary>
565         /// 上週,星期天爲第一天
566         /// </summary>
567         LastWeek,
568         /// <summary>
569         /// 本月
570         /// </summary>
571         ThisMonth,
572         /// <summary>
573         /// 上月
574         /// </summary>
575         LastMonth,
576         /// <summary>
577         /// 今年
578         /// </summary>
579         ThisYear,
580         /// <summary>
581         /// 去年
582         /// </summary>
583         LastYear
584     }
585 
586 }
View Code

 

我的覺着,雖然代碼通常般,但裏面有很多小技巧仍是很不錯的,適合那些比我還新的新手學習一下,好比時間校驗,,那個真的是傷透了心

若是你們發現了有什麼bug,歡迎指出,或者有比較有趣的點子也歡迎互相交流,,,嗯,就醬紫,我去糾結TreeView控件綁值的問題,,

相關文章
相關標籤/搜索