RemoteAttribute Class
RemoteAttribute Class
Provides an attribute that uses the jQuery validation plug-in remote validator.
表单中的输入项,有些是固定的,不变的验证规则,比如字符长度,必填等。但有些是动态的,比如注册用户名是否存在这样的检查,这个需要访问服务器后台才能解决。这篇文章将会介绍MVC中如何使用【RemoteAttribute】来解决这类验证需求,同时会分析【RemoteAttribute】的不足,以及改进的方法.
本文相关的源代码在这里 MVC-Remote-Validation.zip
一, RemoteAttribute验证使用
如果需要用户把整个表单填完后,提交到后台,然后才告诉用户说,“你注册的用户已经被占用了,请换一个用户名”,估计很多用户都可能要飚脏话了.
MVC中的Remote验证是通过Ajax实现的,也就是说,当你填写用户名的时候,就会自动的发送你填写的内容到后台,后台返回检查结果。
1. 实现Remote验证非常简单,首先需要有个后台的方法来响应验证请求, 也就是需要创建一个Controller, 这里我们用ValidationController:
public class ValidationController : Controller { public JsonResult IsEmployeeNameAvailable(string employeeName) { //这里假设已经存在的用户是”justrun”, 如果输入的名字不是justrun,就通过验证 if (employeeName != "justrun") { return Json(true, JsonRequestBehavior.AllowGet); } return Json("The name 'justrun' is not available, please try another name.", JsonRequestBehavior.AllowGet); } }
2. 接着在我们的Employee Model上应用上RemoteAttribute
public class Employee { public int EmpId { get; set; } [DisplayName("Employee Name")] [Remote("IsEmployeeNameAvailable", "Validation")] //使用RemoteAttribute,指定验证的Controller和Action public String EmployeeName { get; set; } }
3. 对应的View
@using (Html.BeginForm()) { @Html.AntiForgeryToken() @Html.ValidationSummary() <fieldset> <legend>Registration Form</legend> <ol> <li> @Html.LabelFor(m => m.EmployeeName) @Html.EditorFor(m => m.EmployeeName) @Html.ValidationMessageFor(m => m.EmployeeName) </li> </ol> <input type="submit" value="Register" /> </fieldset> }
4. 最后,看看验证的效果
通过firebug能够看到,在填写表单的过程中,会不断的把表单的EmployeeName发送到我们指定的Controller, Action上做验证。
二, RemoteAttribute的局限性
使用 【RemoteAttribute】 来做远端验证的确是很棒– 它会自动的发起AJAX请求去访问后台代码来实现验证. 但是注意, 一旦表单提交了,就不会在存在这个验证了。比如当我用上【Required】这个验证标签的时候,无论在客户端还是服务器端,都存在着对于必填项的验证。服务器端可以通过ModelState.IsValid非常容易地判断,当前提交到后台的表单数据是否合法。但是【RemoteAttribute】只有客户端验证,而没有服务器端验证。 也就是说,如果用户的浏览器中,关闭js,我们的Remote检查就形同虚设。
是不是非常意外, 当接触Remote验证的时候,原以为默认的就会认为它会和其它验证标签一样。所以使用RemoteAttribute验证,是存在一定的安全隐患的。
三, RemoteAttribute的改进
先介绍一下对于RemoteAttribute的改进思路:
如果我们也想让RemoteAttribute和其它的验证特性一样工作,也就是说,如果不符合Remote的验证要求,我们希望ModelState.IsValid也是false, 同时会添加上相应的ModelError. 这里选择在MVC的Model binding的时候,做这个事情,因为在Model Binding的时候,正是将表单数据绑定到对应的model对象的时候。只要在绑定的过程中,如果发现Model中的属性有使用RemoteAttribute, 我们调用相应的验证代码。验证失败了,就添加上对于的ModelError.
由于涉及到了Model Binding和Atrribute的使用,如果有兴趣的,可以先看看这2篇文章:
Asp.net MVC使用Model Binding解除Session, Cookie等依赖
.Net Attribute详解(上)-Attribute本质以及一个简单示例
原文有具体的实现,可以去原文看。
背后的原理
Remote Validation In MVC 5 Using Remote Attribute
Parameters which need to be added when decorating a property with Remote attribute.
- IsUserNameAVailable – this is the method which will get invoked
- Users - controller where the above method belongs
- ErrorMessage - if validation failed, this message will be displayed
Include the below references in Create.cshtml file. jQuery, jquery.validate and jquery.validate.unobtrusive script files are required for remote validation to work.
<script src="~/Scripts/jquery-1.10.2.min.js"></script> <script src="~/Scripts/jquery.validate.min.js"></script> <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
Css also can be referenced
<linkhref="~/Content/Site.css"rel="stylesheet"/>
Make sure ClientValidation and UnobtrusiveJavaScript are enabled in web.config,
Unobstrusive JavaScript Validation
One of the more useful things MVC includes is Unobtrusive Validation with the usage of the jQuery Validate plugin and the Unobtrusive library.
This lightweight library allows us to add validation to our MVC views without any additional client-side coding;
we only have to use attributes like RequiredAttribute and RangeAttribute and include the correct script files.
Enabling and Disabling Client-Side Validation at Application Level
- <appSettings>
- <addkey="ClientValidationEnabled"value="true"/>
- <addkey="UnobtrusiveJavaScriptEnabled"value="true"/>
- </appSettings>
相关文章
- c#实例化继承类,必须对被继承类的程序集做引用 .net core Redis分布式缓存客户端实现逻辑分析及示例demo 数据库笔记之索引和事务 centos 7下安装python 3.6笔记 你大波哥~ C#开源框架(转载) JSON C# Class Generator ---由json字符串生成C#实体类的工具
- Java Jad 反编译class文件
- 21Vue - 绑定 HTML Class(对象语法)
- sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class异常解决方法
- Class.forName和ClassLoader到底有啥区别
- classes目录中没有class文件的一个原因
- There is no type initializer in Swift----One answer is to use static, it is the same as class final.
- js中设置元素class的三种方法小结
- Android Unable to find source java class:<File>because it does not belong to any of the source dirs:
- 严重: Exception sending context initialized event to listener instance of class org.springframework.we
- java.lang.IllegalAccessError: tried to access method org.apache.poi.util.POILogger.log from class org.apache.poi.openxml4j.opc.ZipPackage
- Java多线程基础(一)---线程安全(synchronized关键字this锁和class锁分析)
- idea 在新建一个class的时候可以选择继承的父类
- ES6 Class类的继承