ASP.NET MVC验证 - jQuery异步验证
本文主要体验通过jQuery异步验证。
在很多的教材和案例中,MVC验证都是通过提交表单进行的。通过提交表单,可以很容易获得验证出错信息。因为,无论是客户端验证还是服务端验证,总能找到与Model属性或验证特性对应的html元素和属性,并把错误信息显示出来。可是,在实际项目中,经常会遇到需要异步提交的情况。那么,如何把服务端的验证错误信息传递给前端视图呢?
□ 思路
1、服务端的验证错误信息是可以收集起来的以json形式传递个视图的。
2、服务端把错误信息存放在一个字典集合Dictionary<string, object>,让key是属性名,value是错误信息。
3、前台视图中,显示错误信息的元素id,比方说是Err_Name,当遍历从服务端传来的字典集合时,取出key,然后把错误信息动态赋值给$('#Err_' + key)。
View model
using System;
using System.ComponentModel.DataAnnotations;
namespace DataAnnotationAjax.Models
{
public class Student
{
public int Id { get; set; }
[Required(ErrorMessage = "姓名为必填项")]
[Display(Name = "姓名")]
public string Name { get; set; }
[Required(ErrorMessage = "分数是必选项")]
[Range(60, 100, ErrorMessage = "分数必须在60和100之间")]
[Display(Name = "分数")]
public int Score { get; set; }
[Display(Name = "招收日期")]
public DateTime Enrollment { get; set; }
}
}
模拟一个仓储层,负责数据的初始化、添加和显示
using System;
using System.Collections.Generic;
using DataAnnotationAjax.Models;
namespace DataAnnotationAjax.Service
{
public static class StudentRepository
{
private static int _idSeed = 1;
private static readonly List<Student> _students = new List<Student>();
static StudentRepository()
{
Random rand = new Random();
for (int i = 0; i < 3; i++)
{
var student = new Student();
int id = _idSeed++;
student.Id = id;
student.Name = "姓名" + id.ToString();
student.Score = (60 + Convert.ToInt16(rand.NextDouble()*40));
student.Enrollment = DateTime.Now;
_students.Add(student);
}
}
public static void AddStudent(Student stu)
{
stu.Id = _idSeed++;
stu.Enrollment = DateTime.Now;
_students.Add(stu);
}
public static List<Student> GetStudents()
{
return _students;
}
}
}
BaseController
前台视图为了显示错误信息等,需要控制器传来的json可能包含如下构成:
1、是否验证通过:这个bool值很容易通过ModelState拿到。
2、错误信息的字典集合:每个控制器都有可能用到,可以把获取错误信息的字典集合方法放到一个基控制器中去。
3、再加一个福利:有时希望部分视图以字符串形式传递给某一视图,那就把根据视图名称和model返回视图字符串的方法也放到基控制器中。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace DataAnnotationAjax.Controllers
{
public class BaseController : Controller
{
/// <summary>
/// 把部分视图转换成string
/// </summary>
/// <param name="viewName">部分视图名称</param>
/// <param name="model">view model</param>
/// <returns>部分视图字符串</returns>
public string RenderPartialViewToString(string viewName, object model)
{
ViewData.Model = model;
using (var sw = new StringWriter())
{
//根据部分视图名称+ControllerContext获得ViewEngineResult
//ViewEngineResult中有View属性
var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName); //创建ViewContext对象实例
var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw); //把ViewEngineResult中的视图渲染到StringWriter实例中
viewResult.View.Render(viewContext,sw); //获取视图string
return sw.GetStringBuilder().ToString();
}
} /// <summary>
/// 获取ModelState中的错误信息,以字典集合的形式返回
/// </summary>
/// <returns></returns>
public Dictionary<string, object> GetErrorFromModelState()
{
var errors = new Dictionary<string, object>();
foreach (var key in ModelState.Keys)
{
if (ModelState[key].Errors.Count > 0)
{
errors[key] = ModelState[key].Errors;
}
}
return errors;
}
}
}
HomeController
HomeController做了:
1、显示一个异步提交的视图Index.cshtml
2、完成了验证通过情况下的数据添加。
3、不管是否验证通过,都要返回json字符串。
using System.Web.Mvc;
using DataAnnotationAjax.Models;
using DataAnnotationAjax.Service;
namespace DataAnnotationAjax.Controllers
{
public class HomeController : BaseController
{
public ActionResult Index()
{
return View(StudentRepository.GetStudents());
}
[HttpPost]
public ActionResult AddStudent()
{
var student = new Student();
var valid = TryUpdateModel(student);
string studentPartialViewHtml = string.Empty;
if (valid)
{
StudentRepository.AddStudent(student);
var students = StudentRepository.GetStudents();
studentPartialViewHtml = RenderPartialViewToString("Students", students);
}
return Json(new {Valid = valid, Errors = GetErrorFromModelState(), StudentsPartial = studentPartialViewHtml});
}
}
}
部分视图Students.cshtml
@model IEnumerable<DataAnnotationAjax.Models.Student> <table>
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Score)
</th>
<th>
@Html.DisplayNameFor(model => model.Enrollment)
</th>
</tr> @foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Score)
</td>
<td>
@item.Enrollment.ToString("yy-MM-dd")
</td>
</tr>
} </table>
Index.cshtml异步提交的界面
@model IEnumerable<DataAnnotationAjax.Models.Student>
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<style type="text/css">
.errormsg {
color: red;
}
</style>
<div>
<table cellpadding="0px">
<tr>
<td>姓名</td>
<td><input type="text" id="Name" /></td>
</tr>
<tr>
<td></td><td colspan="2"
id="Err_Name" class="errormsg"></td>
</tr>
<tr>
<td>分数</td>
<td><input type="text" id="Score" /></td>
<td>
<button id="btnAddStudent">添加学生</button>
<button id="btnClear">清空</button>
</td>
</tr>
<tr>
<td></td><td colspan="2"
id="Err_Score" class="errormsg"></td>
</tr>
</table>
</div>
<div id="divStudent">
@{Html.RenderPartial("Students",Model);}
</div>
@section scripts
{
<script type="text/javascript">
$(function() {
$('#btnAddStudent').click(function() {
var data = {
Name: $.trim($('#Name').val()),
Score: $.trim($('#Score').val())
};
$.ajax({
cache: false,
type: "POST",
url: '@Url.Action("AddStudent", "Home")',
data: data,
dataType: "json",
success: function(data) {
if (data.Valid) {
$('#divStudent').html(data.StudentsPartial);
$('input').val("");
return;
}
$.each(data.Errors, function(key, value) {
if (value != null) {
$('#Err_' + key).html(value[value.length - 1].ErrorMessage);
}
});
},
error: function(xhr) {
alert(xhr.responseText);
alert("数据没有能提交到服务器!");
}
});
});
$('#btnClear').click(function() {
$('.errormsg').html("");
$("input").val("");
});
$("input").keyup(function() {
var $errorDiv = $("#Err_" + this.id);
if ($errorDiv.html() !="") {
$errorDiv.html("");
}
});
});
</script>
}
几个关键点:
1、显示错误信息的元素id的命名有讲究的:Err_Name,Name与Model中的属性一致。
2、遍历服务端传来的错误信息字典集合时,对每个属性,即key,拿的是最近一次错误:$('#Err_' + key).html(value[value.length - 1].ErrorMessage)。
没有填写信息报错:
填写分数不在定义区间报错:
全部填写正确,验证通过,把部分视图以string形式返回并加载到页面区域中:
ASP.NET MVC验证 - jQuery异步验证的更多相关文章
- MVC验证11-对复杂类型使用jQuery异步验证
原文:MVC验证11-对复杂类型使用jQuery异步验证 本篇体验使用"jQuery结合Html.BeginForm()"对复杂类型属性进行异步验证.与本篇相关的"兄弟篇 ...
- 在ASP.NET MVC中使用Knockout实践06,自定义验证、异步验证
在上一篇中体验了Knockout.Validation的基本验证,本篇体验自定义验证和异步验证. 自定义验证规则 ko.validation有一个rules属性,专门用来存放验证规则,它是一个键值对集 ...
- ASP.NET MVC学习之模型验证篇
一.学习前的一句话 在这里要先感谢那些能够点开我随笔的博友们.慢慢的已经在博客园中度过一年半了,伊始只是将博客园作为自己学习的记录本一样使用,也不敢将自己的随笔发表到博客园首页,生怕自己的技艺不高,反 ...
- ASP.NET MVC如何实现自定义验证(服务端验证+客户端验证)
ASP.NET MVC通过Model验证帮助我们很容易的实现对数据的验证,在默认的情况下,基于ValidationAttribute的声明是验证被使用,我们只需 要将相应的ValidationAttr ...
- MVC验证08-jQuery异步验证
原文:MVC验证08-jQuery异步验证 本文主要体验通过jQuery异步验证. 在很多的教材和案例中,MVC验证都是通过提交表单进行的.通过提交表单,可以很容易获得验证出错信息.因为,无论是客户端 ...
- 【ASP.NET MVC系列】数据验证和注解
[01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作篇)(下) [04]浅谈ASP. ...
- ASP.NET MVC学习之模型验证详解
ASP.NET MVC学习之模型验证篇 2014-05-28 11:36 by y-z-f, 6722 阅读, 13 评论, 收藏, 编辑 一.学习前的一句话 在这里要先感谢那些能够点开我随笔的博友们 ...
- ASP.NET MVC中使用窗体验证出现上下文的模型在数据库创建后发生更改,导致调试失败(一)
在ASP.NET MVC中使用窗体验证.(首先要明白,验证逻辑是应该加在Model.View和Controller哪一个里面?由于Model的责任就是负责信息访问与商业逻辑验证的,所以我们把验证逻辑加 ...
- ASP.NET MVC使用jQuery来POST数据至数据库中
学习ASP.NET MVC程序,结合jQuery客户端代码,Post数据至数据库去.Insus.NET今天写一个完整性的例子. 在数据库中,创建一个表[dbo].[TestUser]: 既然是把数据存 ...
随机推荐
- CRM-BP相关FUNCTION
获取BP的地址信息:BUPA_ADDRESS_GET_DETAIL 修改BP的信息:CRM_WAP_BP_CHANGE BUTO50存放2个BP之间的关系 获取BP的角色 BAPI_BUPA_ROLE ...
- Android ListView快速定位(二)
方法二:android:textFilterEnabled="true" + Filter 这个属性在android.widget.AbsListView下,要求adapter必须 ...
- WebStorm 6.0下运行pomelo项目
最近想使用WebStorm来写pomelo,初次使用WebStorm,网上找了老半天根本没有介绍WebStorm如何创建或者打开运行pomelo的教程,网易pomelo官网介绍的使用 WebStorm ...
- jQuery 学习笔记(未完待续)
一.jQuery概述 宗旨: Write Less, Do More. 基础知识: 1.符号$代替document.getElementById()函数 2.使 ...
- js 三元运算符以及|| 和 && 测试
var a = '0';var b = a ? 'me':'hi'; console.log(b);//false 有: undefined , 0, '', false,null//true ...
- Using the EventManager
Using the EventManager This tutorial explores the features of zend-eventmanager in-depth. Terminolog ...
- MS OFFICE 2010破解版安装
受人所托发布一个MS OFFICE 2010破解版的傻瓜安装教程,刚好新本本也没有安装,安装过程中截了几个图就搞定了. 安装包: http://www.itopdog.cn/soft/office20 ...
- Java基础知识强化之多线程笔记04:并行和并发 区别
1. 并发 和 并行区别 (1)并发:(单核) 并发,是在同一个cpu上同时(不是真正的同时,而是看来是同时,因为cpu要在多个程序间切换)运行多个程序. 并发是指两个任务都请求运行,而处理器只能按受 ...
- 如何在C#中循环一个枚举
在C#中要想迭代循环一个枚举,最容易想到的办法是直接进行循环,如下代码所示: public enum Suit { Spades, Hearts, Clubs, Diamonds } publ ...
- 最小生成树------Prim算法
定义:设G=(V,E)是一个无向连通图.如果G的生成子图T=(V,E’)是一棵树,则称T是G的一棵生成树(Spanning Tree). 应用生成树可以得到关于一个电网的一组独立的回路方程.第一步是要 ...