zoukankan      html  css  js  c++  java
  • ASP.NET MVC3 读书笔记四(数据注解和验证)

    验证在表单数据来说起到非常重要的作用,一般我们的处理是通过js来进行前端的验证,对于重要的数据还进行相应的后端数据验证;

             如果觉得验证是令人望而生畏的繁琐的事情,那么值得高兴的是ASP.NET MVC框架可以帮助处理这些琐事;并且可以很好得支持前端JS验证和后端服务器验证;毕竟对于重要的表单数据来说前端JS还是只起到了进站口的检查,通过一些工具可以轻易的破掉js的验证;但对于服务器验证也并不是万无一失,只是完全强度会高很多;

             MVC主要是通过Model的方式进行数据注解和验证,那么就需要实体类的支持;我们使用EF CodeFirst来进行实体与数据库的相应交互;

    以下说明的表单提交方式为ajax提交;

    View Code
    @using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "test", Url = "/Student/SaveEmploye" }))
        {
            @Html.ValidationSummary(true)
            <div id="test">
            </div>
            <table id="ITable" border="1">
                <tr>
                    <td style=" 120px" >
                        姓名:
                    </td>
                    <td style=" 320px; text-align: left" colspan="3" >
                        @Html.EditorFor(model => model.EmployName)<font color="red">*</font>
                        @Html.ValidationMessageFor(model => model.EmployName)
                    </td>
                </tr>
                <tr>
                    <td style=" 100px" >
                        邮箱:
                    </td>
                    <td style=" 300px; text-align: left" >
                        @Html.EditorFor(model => model.Email)<font color="blue">*</font>
                        @Html.ValidationMessageFor(model => model.Email)
                    </td>
                    <td style=" 100px" >
                        QQ:
                    </td>
                    <td style=" 300px; text-align: left" >
                        @Html.EditorFor(model => model.QQ)<font color="blue">*</font>
                        @Html.ValidationMessageFor(model => model.QQ)
                    </td>
                </tr>
                <tr>
                    <td style=" 100px" >
                        家庭电话:
                    </td>
                    <td style=" 300px; text-align: left" >
                        @Html.EditorFor(model => model.HomePhone)<font color="blue">*</font>
                        @Html.ValidationMessageFor(model => model.HomePhone)
                    </td>
                    <td style=" 100px" >
                        移动电话:
                    </td>
                    <td style=" 300px; text-align: left" >
                        @Html.EditorFor(model => model.MobilePhone)<font color="blue">*</font>
                        @Html.ValidationMessageFor(model => model.MobilePhone)
                    </td>
                </tr>
            </table>  
            <div style="background-color: #efefef;  100%; height: 30px; border: 0px; margin-bottom: 0px;
                margin-top: 10px; text-align: center">
                <input type="submit" value="保存" id="save" class="btn" style=" 80px; height: 25px; margin-top: 2px; margin-left: 2px;"
                    onclick="return CheckForm('save')" />
                <input type="button" value="关闭" class="btn" style=" 80px; height: 25px; margin-top: 2px"
                    onclick="cl()" />
                <input type="button" value="刷新" class="btn" style=" 80px; height: 25px; margin-top: 2px"
                    onclick="reload.click();" />
            </div>
        }

    上面为表单内容,提交到Student的控制器中的SaveEmploye的方法(action)

    如果要在提交前,先通过js验证,必须引入如下js

    <!--页面验证-->
        <script src="/Scripts/jquery.validate.min.js" type="text/javascript"></script>
        <script src="/Scripts/jquery.validate.unobtrusive.js" type="text/javascript"></script>

    如果要接收到ajax后台的回传信息,则必须引入如下js

    <!--ajax提交SuccessCallBack-->
        <script src="/Scripts/jquery.unobtrusive-ajax.js" type="text/javascript"></script>

    以上的js前提是必须先引用jquery;

    后台保存方法为:

    View Code
    public ActionResult SaveEmploye(UserModel usermodel)
            {
                if (ModelState.IsValid)
                {
                    if (usermodel.EmployGUID == new Guid())    //新增
                    {
                        usermodel.EmployGUID = Guid.NewGuid();
                        if (usermodel.Sex == "")
                        {
                            usermodel.Sex = "男";
                        }
                        usermodel.IsDisabeld = 1;
                        usermodel.IsLocked = 1;
                        sm.SaveEmploye(usermodel);
                        return JavaScript("SuccessCallBack('" + usermodel.EmployGUID + "')");
                    }
                    else   //修改
                    {
                        usermodel.ModifiedOn = DateTime.Now;
                        sm.Update(usermodel);
                        return JavaScript("SuccessCallBack('" + usermodel.EmployGUID + "')");
                    }
                }
                return JavaScript("SuccessCallBack('error')");
            }

    做好以上工作,在可以进行相应的注解描述;

    1、  Required

    必填验证,在一般的表单中,会有一些必填项;此时我们就可以用到Required;比如用户名;

    [Required]
    public string EmployName { get; set; }

    在字段上面加上注解信息后,在ajax提交前(客户端开启js验证,并且引入上面的验证js),会自动验证

    如果,客户端禁止了js脚步执行,那么在保存方法中可以自动进行服务器验证,在上面保存方法中写上ModelState.IsValid返回true即表示服务器端的验证成功;

    如果要自定义错误的描述信息,则可以按照如下来写:

    [Required(ErrorMessage="用户名不能为空")]
            public string EmployName { get; set; }

    如果要显示出文本框变色和红色字体提示,引入如下样式即可

    <link href="/Content/Site.css" rel="stylesheet" />

    2、  StringLength

    StringLength是对输入的字符的长度进行限制,比如

    [Required(ErrorMessage="用户名不能为空")]
            [StringLength(15,ErrorMessage="用户名长度不能操作15个字符")]
            public string EmployName { get; set; }

    此时JS如果输入的字符长度超过15就会自动提示ErrorMessage

    3、  RegularExpression

    这个在熟悉不过,是正则表达式的匹配;我们要验证email格式,就可以按如下来写了

    [RegularExpression(@"^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$", ErrorMessage = "邮箱格式错误")]
            public string Email { get; set; }

    可以很简单的做到邮箱的验证;

    4、  Range

    主要用于验证范围,既可以验证int的范围,也可以验证double的范围;

    [Range(typeof(decimal),"0.00","9.99")]
            public Nullable<decimal> Price { get; set; }

    就会自动的判断区间值;

    以上4个验证的命名空间在

    【using System.ComponentModel.DataAnnotations;】下面的两个,Compare、Remoto在

    【using System.Web.Mvc;】命名空间下面

    5、  Compare

    当我们需要验证两次Email一致时,就可以用到

    [RegularExpression(@"^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$", ErrorMessage = "邮箱格式错误")]
            public string Email { get; set; }
            [Compare("Email")]
            public string EmailConfirm { get; set; }

    6、  Remote

    用于远程验证数据,比如在录入用户的时候,要先验证用户名是否存在;此时就可以用到Remote

    [Required(ErrorMessage="用户名不能为空")]
            [StringLength(15,ErrorMessage="用户名长度不能操作15个字符")]
            [Remote("CheckEmploye","Student",ErrorMessage="已经存在相同的用户名")]
            public string EmployName { get; set; }

    RemoteCheckEmployeStudent中的一个action

    public JsonResult CheckEmploye(string userName) {
                if ("test".Equals(userName)) {
                    return Json(true, JsonRequestBehavior.AllowGet);
                }
                return Json(false, JsonRequestBehavior.AllowGet);
            }

    7、  自定义验证

    如果碰到非常个性化的验证,我们还是要进行特殊化自定义的验证;

    下面我们以用户名第一个单词必须大写来进自定义验证;

    View Code
    public class FirstUpper:ValidationAttribute
        {
            public FirstUpper() 
            :base("{0} 第一个字母必须大写")
            { 
            }
            protected override ValidationResult IsValid(object value,ValidationContext validationContext)
            {
                if (value != null)
                {
                    var indexStr=value.ToString().Substring(0,1);
                    if (!indexStr.Equals(indexStr.ToUpper()))
                    {
                        var errorMessage = FormatErrorMessage(validationContext.DisplayName);
                        return new ValidationResult(errorMessage);
                    }
                }
                return ValidationResult.Success;
            }
        }
    [FirstUpper]
            public string EmployName { get; set; }

    定义一个类,继承自ValidationAttribute,然后重写IsValid方法,IsValid中的value就是我们需要判断的值,进行相应判断处理后,返回一个ValidationResult对象就可以;

    写完以上,只能在服务器端进行验证,无法在ajax提交前进行验证;

    首先,在上面的类中,必须继承【IClientValidatable】接口并且实现接口的

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
            {
                var rule = new ModelClientValidationRule();
                rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
                rule.ValidationParameters.Add("res", _result);
                rule.ValidationType = "firstupper";
                yield return rule;
            }

    其中_result为自定义的一个属性,可以在前台js里面取到定义在rule.ValidationParameters中的键值对

    Yield为返回一个IEnumerable的迭代;

    此时只是在后台中写好相应的数据返回到js中,js中的验证还是需要我们自己写,才能进行js验证;

    Js写法如下:

    //实现IClientValidatable接口的客户端验证
            if ($.validator && $.validator.unobtrusive) {
                $.validator.unobtrusive.adapters.addSingleVal("firstupper","res");   //适配器  适配器名称要与服务器上的ValidationType对应
                $.validator.addMethod("firstupper", function (value, element, firstupper) {
                    var indexStr = value.substr(0, 1);
                    if (indexStr != indexStr.toLocaleUpperCase()) {
                        return false;
                    }
                    return true;
                });
            }

    Firstupper为后台代码中定义的rule.ValidationType;res为后台定义的键值对;第一行是将validationtype加载到validator适配器中,然后在addMethod对应即可;

    其中firstupper依然为validationtype,回调方法中的第一个value是当前输入的值,element为整个元素对象,firstupper为res对应的键值对的值;进行判断后,页面js会自动打上“EployName第一个字母必须大写”,如果在model实体上写了ErorMessage也会自动的打出自定义的错误信息;自定义验证都必须遵循相应的规范,并且自行判断实现;(js端必须引用验证js);

     以上这种写法是比较同用的自定义注解验证;

    下面可以直接在实体上面进行注解验证;

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
            {
                var indexStr = EmployName.ToString().Substring(0, 1);
                if (!indexStr.Equals(indexStr.ToUpper()))
                {
                    yield return new ValidationResult("EmployName 第一个字符必须大写", new[] { "EmployName" });
                }
            }

    在对应的实体里面实现IValidatableObject,即可直接操作实例的字段进行验证;[好像只能在服务器端验证,在js客户端的验证好像不好实现];

    具体选用哪种验证要看具体的业务需求在进行选择;

    8、  其它注解

    在实体中除了注解一些验证信息外还可以注解其它的信息,比如

    [Display(Name="用户名")]
            public string EmployName { get; set; }

    在通过labelfor的时候就会显示”用户名”,而不显示EmployName;

    [ScaffoldColumn(false)]
            public string EmployName { get; set; }

    在进行EditorForModel进行全字段映射的时候,不会映射EmployName字段

    [DisplayFormat(DataFormatString="{0:c}")]
            public decimal price { get; set; }

    在输入9.0的时候会自动格式化为$9.00

    如果写法【[DisplayFormat(ApplyFormatInEditMode=true,DataFormatString="{0:c}")]】

    则会将$9.00进行回填,所以此处应该设置为flase不回填格式化的值,回填输入的值;

    [ReadOnly(true)]
            public string EmployName { get; set; }

    设置为readonly后,页面在提交后台时,模型不会绑定新增;页面中设置为disable的input都不会重新绑定模型提交后台;

    [HiddenInput]
            public string EmployName { get; set; }

    生成为hiddeninput控件


    作者:Regicidegod
    出处:http://www.cnblogs.com/RegicideGod/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    Head first javascript(七)
    Python Fundamental for Django
    Head first javascript(六)
    Head first javascript(五)
    Head first javascript(四)
    Head first javascript(三)
    Head first javascript(二)
    Head first javascript(一)
    Sicily 1090. Highways 解题报告
    Python GUI programming(tkinter)
  • 原文地址:https://www.cnblogs.com/RegicideGod/p/2892451.html
Copyright © 2011-2022 走看看