MVC DataAnnotations 模型验证

using System.ComponentModel.DataAnnotations;

@Html.ValidationSummary("Errors have occurred:")//显示视图总的验证信息

通过为模型类增加数据描述的 DataAnnotations ,我们可以容易地为应用程序增加验证的功能。DataAnnotations 允许我们描述希望应用在模型属性上的验证规则,ASP.NET MVC 将会使用这些DataAnnotations ,然后将适当的验证信息返回给用户。

常用的 DataAnnotations

1.Required 

属性值必须非空或者不能只是空格,如果允许全空格可以[Required(AllowEmptyStrings = true)]

2.DisplayName 显示名 – 定义表单字段的提示名称

3.StringLength 

字符串长度不能超过给定的最大长度,也可以指定最小长度:[StringLength(10, MinimumLength=2)]

4.Range 范围 – 数字的可输入范围[Range(10, 20)] 

属性值必须在指定的数值范围内,可以使用数值类型的最大最小值比如int.MinValue、int.MaxValue

5.Bind 绑定 – 列出在将请求参数绑定到模型的时候,包含和不包含的字段

6.ScaffoldColumn 支架列 - 在编辑表单的时候,需要隐藏起来的的字符

[ScaffoldColumn(true|false)]

7.Compare 比较 - 与制定的字段值进行比较 具体见代码

[Compare("MyOtherProperty")]两个属性必须相同值,比如我们要求用户重复输入两次邮件地址时有用

8.RegularExpre ssion 正则表达式匹配

字符串值必须匹配正则表达式,默认大小写敏感,可以使用(?i)修饰符关闭大小写敏感,比如[RegularExpre ssion("(?i)mypattern")]

9.DataType 在前端显示的文本框类型

10. Remote 服务端验证

11. [Editable(false)] //放在主键上显示不可修改

将数据验证代码放入Model中,在BLL中验证数据已经很好了,但是又出现了一个问题:一个Model,很多限制是固定的,比如长度不能超过20个字符,但是我在BLL中有很多过程,比如修改,删除等,那岂不是要在所有的过程中都多这个进行验证?但是,Model的名字有没有超过20个字符是的Model层的事情。

添加引用System.ComponentModel.DataAnnotations.dll

Model

using System;
using System.Collections.Generic;
using System.Linq; using System.Web;
using System.ComponentModel.DataAnnotations;
namespace MvcApplication1.Models {
      public class UserModel{
         [Editable(false)]
          Public int ID{get;set;}
          public string Name { get; set; }
         //属性前加上Attribute
    //这里验证输入数据是否是bool类型且为true,使用这个自定义验证特性很简单:
  MustBeTrue(ErrorMessage="You must accept the terms")] 
  public bool TermsAccepted { get; set; } 
    [Required(ErrorMessage = "密码不能为空")]
    [StringLength(20, ErrorMessage = "密码长度不能超过20个字符")]
       public string Password { get; set; }
     }
 }

  这里没有取消掉BLL中的验证,2种验证可以混合使用

 Controller

          [HttpPost]

          //MVC在传入这个Model的时候已经进行了验证,并且把错误放去了

ModelState

public ActionResult Exp4(Models.UserModel user)
{
    try
     {//别的不变,除了这里,我们需要传入ModelState.IsValid
          BLL.UserBLL.Edit(user,ModelState.IsValid);
     }
     catch (ModelExceptions e)
       {e.FillModelState(ModelState); }
     if (ModelState.IsValid)
       {return RedirectToAction("Index"); }
     else
       {return View("Exp1", user); }
}

BLL

public static void Edit(Models.UserModel user,bool IsValid)
{
      var e = new ModelExceptions();
      if (user.Name.Length > 20)
      {
          e.AddError("Name", "名字不得超过20个字符");
       }
       //别的不变,但在这里,除了要判断e中是否有错误外,还要判断ModelState中是否有错误
       if (e.IsValid && IsValid)
       { //在这可以写一些代码,因为完成了验证,就可以开始更新数据库 
    }
else {throw e;} }

为什么要把ModelState.IsValid传入BLL?因为Model验证是在这个Model传入这个方法的时候就已经完成的,如果不传入,那BLL验证中虽然没错误,但不代表整个过程没有错误。对数据库的操作要知道完整的验证信息,如果不传入,会导致程序BUG

客户端验证

  任何平台都可以靠js来实现客户端验证,但是我这里探讨的是MVC的数据验证。那MVC的客户端数据验证有什么不同呢?  在View里添加一行代码:(注意要添加在Form前)@Html.EnableClientValidation();

注意点:这里,其实是这个函数把Model验证转换成了javascript代码,对!它只能转换Model验证,BLL验证无法转换,因为BLL验证涉及到复杂的代码,不可能全部转换成javascript吧?并且BLL验证很多还需要和数据库交互。  那如果想把BLL验证也做成“客户端”验证怎么办?(只有可能用ajax实现无刷新验证,而不是真正的客户端验证)

关于Model层数据验证的一些验证规则与相关验证属性标签小集

(1)常规验证(必填字段、字符串长度、正则表达式验证、范围验证<</span>数值、日期>等)

 1. 必填字段

  [Required]

  public string FirstName { get; set; }

 2. 字段长度 至多n位:

  [StringLength(160)]

  public string FirstName { get; set; }

 要求至少n位:

  [StringLength(160, MinimumLength=3)]

   public string FirstName { get; set; }

 3. 正则验证

  [RegularExpre ssion(@”[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}”)]

   public string Email { get; set; }

4. 范围

 [Range(35,44, UIHint("IntSlider"))] //左右托动块

public int Age { get; set; }

 小数的情况:

[Range(typeof(decimal), “0.00”, “49.99”)]

 public decimal Price { get; set; } 

5. 服务端参与的验证

  [Remote(“CheckUserName”, “Account”, ErrorMessage = "该姓名已存在")]

   public string UserName { get; set; }

Remote异步请求验证,在[HttpGet]时获取指定Controller里面的指定方法验证, 次方法必须是[HttpGet]标记的,返回类型为Json类型的JavaScript对象。

   然后在AccountController里指定一个CheckUserName方法:

public JsonResult CheckUserName(string username)
 {
      var result = Membership.FindUsersByName(username).Count == 0;
      return Json(result, JsonRequestBehavior.AllowGet);
}

6. 比较

  [RegularExpre ssion(@”[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}”)]

  public string Email { get; set; }

  [Compare(“Email”)]

  public string EmailConfirm { get; set; }

public string EmailConfirm { get; set; } 

7. 自定义错误消息

正则:

[RegularExpre ssion(@”[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}”,ErrorMessage=”Email doesn’t look like a valid email address.”)]

public string Email { get; set; } 

具体示例如下:

[DisplayName("分组名称")]

[Required(ErrorMessage = "请输入账号")]

[StringLength(50, ErrorMessage = "请勿输入超过 50 个字")]

public string Name { get; set; }

[DisplayName("排序字段")]

[DataType(DataType.Password)]

[Required(ErrorMessage = "请输入排序字段")]

[RegularExpre ssion(@"^([\d]+)$", ErrorMessage = "请输入正确的Email.")]

public string Sequence { get; set; }

[DisplayName("备注")]

[DataTyle(DataType.MultilineText)]//数据显示为多文本

[Required(AllowEmptyStrings=true, ErrorMessage = "请输入中文姓名")]

[StringLength(50, ErrorMessage = "请勿输入超过 50 个字")]

public string Describe { get; set; }

[DisplayName("账号")]

[Required(ErrorMessage = "请输入账号")]

[StringLength(50, ErrorMessage = "请勿输入超过 50 个字")]

public string Account { get; set; }

[DisplayName("密码")]

[DataType(DataType.Password)]

[Required(ErrorMessage = "请输入密码")]

[StringLength(50, ErrorMessage = "请勿输入超过 50 个字")]

public string Password { get; set; }

[Required]

[DataType(DataType.Password)]

[Display(Name = "Current password")]

public string OldPassword { get; set; }

[Required]

[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]

[DataType(DataType.Password)]

[Display(Name = "New password")]

public string NewPassword { get; set; }

[Display(Name = "确认密码")]

[Compare("LogPassword", ErrorMessage = "密码必须一致")]

public virtual string LogPasswordConfirm { get; set; }

[Display(Name = "Remember me?")]

public bool RememberMe { get; set; }

[DisplayName("姓名")]

[Required(ErrorMessage = "请输入姓名")]

[StringLength(50, ErrorMessage = "请勿输入超过 50 个字")]

public string ChName { get; set; }  (PMS已有)

[DisplayName("昵称")]

[Required(ErrorMessage = "请输入昵称")]

[StringLength(50, ErrorMessage = "请勿输入超过 50 个字")]

public string NickName { get; set; }

[Display(Name = "出生日期")]   

//[Range(typeof(DateTime), "2011-12-31", "1950-1-1", ErrorMessage = "{0}的范围是{1}到{2}")]

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]//显示格式

public virtual DateTime? Birthday { get; set; } //表示值可为Null

[DisplayName("年龄")]

[Range(1, int.MaxValue, ErrorMessage = "请输入大于等于1的数")]

public int Age { get; set; }

[DisplayName("Email")]

[Required(ErrorMessage = "请输入Email")]

[StringLength(255, ErrorMessage = "请勿输入超过 255 个字")]

[RegularExpre ssion(@"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4})$", ErrorMessage = "请输入正确的Email.")]

[DataType(DataType.EmailAddress)]

public string Email { get; set; } (PMS已有)

[DisplayName("电话号码")]

[RegularExpre ssion(@"^((0\d{2,5}-)|\(0\d{2,5}\))?\d{7,8}(-\d{3,4})?$", ErrorMessage = "电话格式有误。\n有效格式为:\n①本区7或8位号码[-3或4位分机号码,可选]\n②(3~5位区号)7或8位号码[-3或4位分机号码,可选]\n③3~5位区号-7或8位号码[-3或4位分机号码,可选]\n示例:023-12345678;(023)1234567-1234")]

public string Phone { get; set; }

[Display(Name = "身份证号码")]

[RegularExpre ssion(@"\d{17}[\d|X]|\d{15}", ErrorMessage = "{0}的格式不正确")]

public virtual string IdentityNo { get; set; }

[DisplayName("是否为管理员")]

public bool IsAdmin { get; set; }

[DisplayName("代表图示")]

[Required(ErrorMessage = "请选择代表图示")]

[Range(1, 3, ErrorMessage = "输入的值必须介于 1 到 3之间")]

public int AvatarIcon { get; set; }

[Display(Name = "逻辑删除标识")]

public virtual int IsLogicDelete { get; set; }

[DisplayName("验证码")]

public string AuthCode { get; set; }

[DisplayName("创建日期")]

public DateTime CreateTime { get; set; }

[DisplayName("网址")]

[RegularExpre ssion(@"http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?", ErrorMessage = "请输入合法的网址!\n示例:

https://abc.a;http://www.abc.dd") ]

public string Httpaddress { get; set; }

普通文本:

[Required(ErrorMessage=”Your last name is required”)]

[StringLength(160, ErrorMessage=”Your last name is too long”)]

public string LastName { get; set; }

占位符:

[Required(ErrorMessage=”Your {0} is required.”)]

[StringLength(160, ErrorMessage=”{0} is too long.”)]

public string LastName { get; set; }

(2)数据库约束验证

如果不希望用户使用123456这样的过于简单的密码,可以使用check约束来实现:

ALTER TABLE staffinfoes WITH NOCHECK  ADD CONSTRAINT chk_logPassword

CHECK (logPassword NOT IN('123','123123','123456'))

其中,staffinfoes是表名称,chk_logPassword是约束名称,logPassword是列名称

posted @ 2016-05-22 20:07  xszjk  阅读(752)  评论(0)    收藏  举报