zoukankan      html  css  js  c++  java
  • MVC查询数据接收及校验

    本来想写一篇aspx的TreeView控件绑值的文章的,在写案例的时候,写了一半,发现有些地方还得考虑以下,就留待下次了。

    这一篇的话,是最近在开发一个项目的时候,有大量的页面和数据表,需要花式查询,

    后台接收前台传递过来的数据的时候,被虐的欲仙欲死,大量的校验和重复代码,

    后来找到了一种非常不错的方法,分享出来,下面是正文。。。。。

    使用过MVC的人都知道,它有一个非常方便的功能,就是自动绑值,先来一个最简单的:

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

    当从前台传递过来的数据中,有两个参数名字为userName或type时,MVC会自动帮我们将参数类型转好,值给好。

    我们要做的无非是直接使用罢了,但是,当要传递的值非常多的时候,无论是写还是看,都会非常吃力,比如这样:

    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         }

    其实,七个查询参数并不多,当参数数量达到十个,二十个时,相信我,你会炸的,

    一般这个时候,我们可用选择使用对象,就像这样:

     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同样能够帮你将数据依次绑好,同时,代码的复用率也会提高很多,

    现在解决了数据接收的问题,接下来的,就是数据的校验了。

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

    拿到参数后,我们是不能立刻去使用的,需要对参数进行一次校验,校验的目的,就是防止有人恶意传递错误数据给后台,

    若不进行数据校验的话,很容易导致项目崩溃,或者数据丢失等等一系列问题,简单的说一些校验类型吧,

    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控件绑值的问题,,

  • 相关阅读:
    堆、栈、值类型、引用类型分析总结 Part 2
    DataGridView打印
    学习使用ArrayList
    C#与Java之比较
    【原创】串口通信测试程序
    彩色校验码的制作
    C#中使用进度条
    【原创】 Ajax之ModalPopup编程实例
    常用正则表达式
    堆、栈、值类型、引用类型分析总结 Part 1
  • 原文地址:https://www.cnblogs.com/Onlooker/p/7587696.html
Copyright © 2011-2022 走看看