• 蓝色妖姬   2014/7/31 13:21:00
  • ASP.NET MVC3.0 之-Model
  • 关键字: MVC Model 模型
  • asp.net vc 之 asp.net mvc 3.0 新特性之 Model:
    • 通过 Data Annotations 与 jQuery 的结合实现服务端和客户端的双重验证
    • 双重验证中,使客户端实现远程的异步验证
    • 自定义 Data Annotations 与 jQuery,以实现自定义的双重验证

    示例
    Model 中通过 Data Annotations 与 jQuery 的结合实现服务端和客户端的双重验证
    Web.config


    <configuration>
        <!--
            要实现服务端和客户端的双重验证,需要做如下配置,因为双重验证中的客户端验证需要依赖此配置
        -->
        <appSettings>
            <add key="ClientValidationEnabled" value="true"/>
            <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
        </appSettings>
    </configuration>

    User.cs

    /*
     * 在 asp.net mvc 3.0 中支持通过 Data Annotations 来实现服务端和客户端的双重验证,需要 jQuery 的支持
     * 所有 Data Annotations 相关的 Attribute 直接用类视图看 System.ComponentModel.DataAnnotations 就行了,详细说明以前写过好多遍了,这里就不重复了
     * 另外 System.Web.Mvc 下有一些新增的 Data Annotations
     */
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Web.Mvc;
    
    namespace MVC30.Models
    {
        public class User
        {
            public int ID { get; set; }
            
            [DisplayName("名字")]
            [Required(ErrorMessage = "名字不能为空")]
            public string Name { get; set; }
    
            [DisplayName("密码")]
            [Required(ErrorMessage = "密码不能为空")]
            public string Password { get; set; }
    
            [DisplayName("确认密码")]
            [Required(ErrorMessage = "确认密码不能为空")]
            [Compare("Password", ErrorMessage="两次密码输入不一致")]
            public string ConfirmPassword { get; set; }
    
            public DateTime DateOfBirth { get; set; }
    
            // 请求时,允许此字段包含 HTML 标记
            [AllowHtml]
            public string Comment { get; set; }
        }
    }

    ValidationDemoController.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    using MVC30.Models;
    
    namespace MVC30.Controllers
    {
        public class ValidationDemoController : Controller
        {
            // 用于演示通过 Data Annotations 实现服务端和客户端的双重验证
            public ActionResult Validation_DataAnnotations()
            {
                var user = new User { ID = 1, Name = "webabcd", DateOfBirth = new DateTime(1980, 2, 14), Comment = "<b>mvp</b>" };
    
                return View(new User());
            }
    
            [HttpPost]
            public ActionResult Validation_DataAnnotations(User user)
            {
                return View(user);
            }
        }
    }

    Validation_DataAnnotations.cshtml

    @model MVC30.Models.User
               
    @{
        ViewBag.Title = "Validation_DataAnnotations";
    }
    
    <h2>ClientValidation</h2>
    
    <!--
        通过 jQuery 实现客户端验证的逻辑,需要引用此 js
    -->
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <!--
        服务端验证与客户端验证的一一对应需要引用此 js
    -->
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
    
    @*
    在 MVC3 中实现客户端验证,不需要添加以下代码
    @{ Html.EnableClientValidation(); }
    *@
    
    @using (Html.BeginForm())
    {
        <fieldset>
            <legend>User</legend>
            <div class="editor-label">
                @Html.LabelFor(model => model.Name)
                (测试方法:空着文本框,然后提交)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>
            <p>
                <input type="submit" value="Create" />
            </p>
        </fieldset>
    }

    Model 中通过 Data Annotations 与 jQuery 的结合实现服务端和客户端的双重验证,其中客户端可以实现远程的异步验证
    User.cs

    /*
     * System.Web.Mvc.Remote(string action, string controller) - 让客户端可以通过 ajax 的方式远程验证
     *     action - 实现验证逻辑的 action,即处理客户端的异步请求的 action
     *     controller - 实现验证逻辑的 controller,即处理客户端的异步请求的 controller
     */
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Web.Mvc;
    
    namespace MVC30.Models
    {
        public class User
        {
            public int ID { get; set; }
            
            [DisplayName("名字")]
            [Required(ErrorMessage = "名字不能为空")]
            [Remote("CheckUserNameExists", "ValidationDemo", ErrorMessage = "名字已存在")]
            public string Name { get; set; }
    
            [DisplayName("密码")]
            [Required(ErrorMessage = "密码不能为空")]
            public string Password { get; set; }
    
            [DisplayName("确认密码")]
            [Required(ErrorMessage = "确认密码不能为空")]
            [Compare("Password", ErrorMessage="两次密码输入不一致")]
            public string ConfirmPassword { get; set; }
    
            public DateTime DateOfBirth { get; set; }
    
            // 请求时,允许此字段包含 HTML 标记
            [AllowHtml]
            public string Comment { get; set; }
        }
    }

    ValidationDemoController.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    using MVC30.Models;
    
    namespace MVC30.Controllers
    {
        public class ValidationDemoController : Controller
        {
            // 用于演示客户端的远程 ajax 异步验证
            public ActionResult Validation_Remote()
            {
                var user = new User { ID = 1, Name = "webabcd", DateOfBirth = new DateTime(1980, 2, 14), Comment = "<b>mvp</b>" };
    
                return View(new User());
            }
    
            [HttpPost]
            public ActionResult Validation_Remote(User user)
            {
                return View(user);
            }
    
            // 用于处理客户端的异步请求,测试时请使用字符串“webabcd”
            [HttpGet]
            public ActionResult CheckUserNameExists(string name)
            {
                return Json(name != "webabcd", JsonRequestBehavior.AllowGet);
            }
        }
    }

    Validation_Remote.cshtml

    @model MVC30.Models.User
               
    @{
        ViewBag.Title = "Validation_Remote";
    }
    
    <h2>ClientValidation</h2>
    
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
    
    @using (Html.BeginForm())
    {
        <fieldset>
            <legend>User</legend>
            <div class="editor-label">
                @Html.LabelFor(model => model.Name)
                (测试方法:在文本框中输入“webabcd”)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>
            <p>
                <input type="submit" value="Create" />
            </p>
        </fieldset>
    }

    Model 中使用更多的 Data Annotations 以及实现自定义的 Data Annotations 和自定义 jQuery 的相关逻辑
    User.cs

    /*
     * 如何使用更多的 Data Annotation
     *     1、在“Tools”中选择“Extension Manager”(安装 NuGet 后会有此选项)
     *     2、搜索“DataAnnotationsExtensions”,然后安装“DataAnnotationsExtensions.MVC3”项目
     *     3、之后就可以使用此项目所支持的多个新的 Data Annotation
     * 如何自定义 Data Annotation
     *     详见:IntegerAttribute.cs
     */
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Web.Mvc;
    
    namespace MVC30.Models
    {
        public class User
        {
            public int ID { get; set; }
            
            [DisplayName("名字")]
            [Required(ErrorMessage = "名字不能为空")]
            [Remote("CheckUserNameExists", "ValidationDemo", ErrorMessage = "名字已存在")]
            public string Name { get; set; }
    
            [DisplayName("密码")]
            [Required(ErrorMessage = "密码不能为空")]
            [Integer(ErrorMessage = "密码必须是整型")]
            public string Password { get; set; }
    
            [DisplayName("确认密码")]
            [Required(ErrorMessage = "确认密码不能为空")]
            [Compare("Password", ErrorMessage="两次密码输入不一致")]
            public string ConfirmPassword { get; set; }
    
            public DateTime DateOfBirth { get; set; }
    
            // 请求时,允许此字段包含 HTML 标记
            [AllowHtml]
            public string Comment { get; set; }
        }
    }

    IntegerAttribute.cs

    /*
     * 自定义 Data Annotation,以实现与 jQuery 结合的客户端和服务端双重验证
     */
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    using System.ComponentModel.DataAnnotations;
    using System.Text.RegularExpressions;
    using System.Web.Mvc;
    
    namespace MVC30.Models
    {
        // 继承 ValidationAttribute 抽象类,重写 IsValid() 方法,以实现服务端验证
        // 实现 IClientValidatable 接口的 GetClientValidationRules() 方法,以实现客户端验证
        public class IntegerAttribute : ValidationAttribute, IClientValidatable
        {
            // 服务端验证逻辑,判断输入是否为整型
            public override bool IsValid(object value)
            {
                var number = Convert.ToString(value);
                return Regex.IsMatch(number, @"^[0-9]+$");
            }
            
            // 客户端验证逻辑,需要结合客户端验证代码,详见 Validation_Custom.cshtml 文件
            public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
            {
                var rule = new ModelClientValidationRule
                {
                    ErrorMessage = this.ErrorMessage,
    
                    // ValidationType - 指定一个 key(字符串),该 key 用于关联服务端验证逻辑与客户端验证逻辑。注:这个 key 必须都是由小写字母组成
                    ValidationType = "isinteger" 
                };
    
                // 向客户端验证代码传递参数
                rule.ValidationParameters.Add("param1", "value1");
                rule.ValidationParameters.Add("param2", "value2");
    
                yield return rule;
            }
        }
    }

    ValidationDemoController.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    using MVC30.Models;
    
    namespace MVC30.Controllers
    {
        public class ValidationDemoController : Controller
        {
            // 用于演示如何使用更多的 Data Annotations 来实现服务端和客户端的双重验证,以及如何自定义 Data Annotations 来实现服务端和客户端的双重验证
            public ActionResult Validation_Custom()
            {
                var user = new User { ID = 1, Name = "webabcd", DateOfBirth = new DateTime(1980, 2, 14), Comment = "<b>mvp</b>" };
    
                return View(new User());
            }
    
            [HttpPost]
            public ActionResult Validation_Custom(User user)
            {
                return View(user);
            }
        }
    }

    Validation_Custom.cshtml

    @model MVC30.Models.User
               
    @{
        ViewBag.Title = "ClientValidation";
    }
    
    <h2>ClientValidation</h2>
    
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
    
    <script type="text/javascript">
    
        // 客户端验证逻辑,判断输入是否为整型
        jQuery.validator.addMethod(
            'checkInteger',
            function (value, element) {
                var reg = new RegExp("^[0-9]+$");
                return (reg.test(value));
            }
        );
    
        // 将客户端验证逻辑通过 ValidationType 与服务端的相关验证逻辑结合起来
        jQuery.validator.unobtrusive.adapters.add(
            'isinteger', // ValidationType,必须全为小写
            ['param1', 'param2'], // 接收 ModelClientValidationRule 中的参数信息
            function (options) {
                options.rules['checkInteger'] = true; // 启用名为 checkInteger 的客户端验证逻辑
                options.messages['checkInteger'] = options.message; // 发生验证错误后的显示信息
                var param1 = options.params.param1; // ModelClientValidationRule 中的参数信息
                var param2 = options.params.param2; // ModelClientValidationRule 中的参数信息
                alert(param1 + " " + param2);
            }
        ); 
    
    </script>
    
    @using (Html.BeginForm())
    {
        <fieldset>
            <legend>User</legend>
            <div class="editor-label">
                @Html.LabelFor(model => model.Name)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>
            <div class="editor-label">
                @Html.LabelFor(model => model.Password)
                (测试方法:在文本框中输入非整型的字符串)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Password)
                @Html.ValidationMessageFor(model => model.Password)
            </div>
            <p>
                <input type="submit" value="Create" />
            </p>
        </fieldset>
    }