原本想寫一篇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 }
我的覺着,雖然代碼通常般,但裏面有很多小技巧仍是很不錯的,適合那些比我還新的新手學習一下,好比時間校驗,,那個真的是傷透了心
若是你們發現了有什麼bug,歡迎指出,或者有比較有趣的點子也歡迎互相交流,,,嗯,就醬紫,我去糾結TreeView控件綁值的問題,,