一起谈.NET技术,ASP.NET MVC中的Json Binding和Validate

  电子商务网站支付功能页面往往会有很多信息,对于这些信息的保存,往往是分步完成的,那么使用Ajax最合适不过了,比如其中的收货人信息模块。这些信息的新建和编辑保存都是用Ajax来完成的。那么有几种方式完成这个操作呢,我想到如下几种。
  先来看看该功能的截图:

  一般情况下这些信息会对应一个实体类,就命名为:ReceiverInfo,简单起见,我定义ReceiverInfo如下:


  1、将需要的值拼接成json文本,再Action里面处理

  首先您需要将要保存的值拼接成一个json文本,类似:


var test = "{ ReceiverId: 5, ReceiverName: 'will', Sex: 'F', CreateDate: '2011-02-21' }";

  然后用Jquery保存到数据库,代码如下:


$.ajax({
url: "/Home/test1",
type: "post",
cache: false,
data: test
});

  然后您在Action里面这样操作:


StreamReader reader = new StreamReader(Request.InputStream);
string bodyText = reader.ReadToEnd();
JavaScriptSerializer js = new JavaScriptSerializer();
ReceiverInfo receiver = js.Deserialize<ReceiverInfo>(bodyText);
//保存。。。

  2、利用自定义的ModelBinder实现


JsonBinder



1 public class JsonBinder<T> : IModelBinder
2 {
3 public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
4 {
5 StreamReader reader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
6 string json = reader.ReadToEnd();
7
8 if (string.IsNullOrEmpty(json))
9 return json;
10
11 JavaScriptSerializer serializer = new JavaScriptSerializer();
12 object jsonData = serializer.DeserializeObject(json);
13 return serializer.Deserialize<T>(json);
14 }
15 }







  我们继承IModelBinder接口,实现其 方法:


public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)

  即可。我们可以在Action里面这样使用:


public ActionResult Test1([ModelBinder(typeof(JsonBinder<ReceiverInfo>))] ReceiverInfo receiverInfo)

  这样我们自定义的 IModelBinder就会取代DefaultModelBinder完成数据绑定。
  3、直接传递一个Json对象

  上面两种方法并没有利用MVC的System.ComponentModel.DataAnnotations进行有效的数据验证。您可能需要自己手动验证,无疑增加了工作量。

  我们试试这种方式。

  前端的写法:


1. var b = {
2. ReceiverId: 5,
3. ReceiverName: "will",
4. Sex: "F",
5. CreateDate: "2011-02-21"};$.ajax({
6. url: "/Home/test1",
7. type: "post",
8. cache: false,
9. data: b,
10. success: function(data) { alert(data.message); },
11. error: function(xhr, a, b) { alert
12. (xhr.responseText); }});

  Action的写法:


public ActionResult Test1(ReceiverInfo receiverInfo)

  我们能正常的得到绑定后的数据。而且我们还能利用System.ComponentModel.DataAnnotations进行数据验证。我们为ReceiverInfo做如下改动:


[System.ComponentModel.DataAnnotations.Required(ErrorMessage = "收货人必须填写")]
public string ReceiverName { get; set; }

  并在前端为ReceiverName赋值为空字符串,再次执行,得到提示:

  很好,不过我们有新的要求了,那就是传递更复杂的对象,比如对象套嵌对象,对象有集合属性,这种方式不能胜任了。
  4、利用MvcFutures的JsonValueProviderFactory

  每一版的MVC都有一个MvcFutures,里面会有一些额外的功能,这些功能有些会加入下一个版本中,而这些功能在某些时候很有用处。我查看了里面的类,发现有一个类JsonValueProviderFactory正是处理复杂对象的提交和数据验证。

  由于json对象需要特定解析才能使用默认的DefaultModelBinder,而这个解析过程需要在ValueProvider阶段完成,所以需要实现特定的ValueProvider给DefaultModelBinder。我们需要实现一个ValueProviderFactory和IValueProvider,而MVC里面的DictionaryValueProvider<TValue>(继承了IValueProvider)已经足够使用了,所以只需要继承ValueProviderFactory实现其方法:public override IValueProvider GetValueProvider(ControllerContext controllerContext)即可,具体代码您可以看JsonValueProviderFactory。

  我们定义另一个类:

ReceiverInfoChild


public class ReceiverInfoChild
{
[System.ComponentModel.DataAnnotations.Required(ErrorMessage = "ChildId必须填写")]
public string ChildId { get; set; }
}

  并为类ReceiverInfo增加一个属性public List<ReceiverInfoChild> ReceiverInfoChild { get; set; }

  我们把JsonValueProviderFactory拿出来放在项目里面,然后在Global.asax里面注册一下,就可以使用了。


1. protected void Application_Start(){
2. AreaRegistration.RegisterAllAreas();
3. RegisterRoutes(RouteTable.Routes);
4. ValueProviderFactories.Factories.Add(new
5. JsonValueProviderFactory());}

  因为JsonValueProviderFactory中有:if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))来判断进来的请求是不是json对象,所以我们提交数据的时候需要这样写:


1. var ReceiverInfo = [
2. {
3. ReceiverInfoChild: [{ ChildId: "1" }, { ChildId: "11"}],
4. ReceiverId: 5,
5. ReceiverName: "will",
6. Sex: "F",
7. CreateDate: "2011-02-21"
8. },
9. {
10. ReceiverInfoChild: [{ ChildId: "2" }, { ChildId: "22"}],
11. ReceiverId: 5,
12. ReceiverName: "will",
13. Sex: "F",
14. CreateDate: "2011-02-21" }
15. ];$.ajax({
16. url: "/Home/test1",
17. type: "post",
18. cache: false,
19. contentType: "application/json;charset=utf-8",
20. data: JSON.stringify(ReceiverInfo),
21. success: function(data) { alert(data.message); },
22. error: function(xhr, a, b) { alert(xhr.responseText); }});

  其中JSON.stringify(ReceiverInfo)是将json对象转换成字符串,您可以到这里下载该类库。

  在Action里面,我们这样写就可以了:


public ActionResult Test1(List<ReceiverInfo> receiverInfo)

  看一下调试的结果:

  完全正常绑定了值。我们再看看数据验证:

  至此,我们实验了四种方案:

  第一种方案,最麻烦,而且容易出错(可能跟我个人不喜欢拼接字符串有关系);

  第二种方案,有一定的通用性,但是不利于数据验证;

  第三种方案,通用,可以进行有效的数据验证,应对一般的需求够用了,但是处理更复杂的对象不行;

  第四种方案,几乎可以处理我们遇到的所有情况

  另外,这是在ASP.NET MVC2中的使用,到了ASP.NET MVC3,微软已经把JsonValueProviderFactory作为内置的功能了。

时间: 2024-10-28 13:09:46

一起谈.NET技术,ASP.NET MVC中的Json Binding和Validate的相关文章

ASP.NET MVC中的Json “.NET研究”Binding和Validate

电子商务网站支付功能页面往往会有很多信息,对于这些信息的保存,往往是分步完成的,那么使用Ajax最合适不过了,比如其中的收货人信息模块.这些信息的新建和编辑保存都是用Ajax来完成的.那么有几种方式完成这个操作呢,我想到如下几种. 先来看看该功能的截图: 一般情况下这些信息会对应一个实体类,就命名为:ReceiverInfo,简单起见,我定义ReceiverInfo如下: 1.将需要的值拼接成json文本,再Action里面处理 首先您需要将要保存的值拼接成一个json文本,类似: var te

一起谈.NET技术,ASP.NET MVC中对数据进行排序的方法

本系列是讲解如何在asp.net mvc中对数据进行展示.排序.分页等的系列文章.在上周的文章中,一步一步教会了大家如何使用ASP.NET MVC框架去的展示数据.在上周的文章中,我们先用Visual Studio创建了一个新的ASP.NET MVC应用程序,接着连接到了Northwind数据库,并展示了如何使用微软的LINQ-SQL的工具去访问数据库中的数据,接着指导如何去实现视图层去展示产品信息及如何设计控制器. 本文是在上一篇文章的例子基础上,展示了如何去实现数据的双向排序.如果你是已经熟

一起谈.NET技术,在ASP.NET MVC中进行TDD开发

TDD介绍 TDD是一种开发方法,全称是Test-Driven development,中文是测试驱动开发.作者是Kent Beck.首先让我介绍一下三种常见的开发方式: 第一种:先Coding,然后Bug Fix. 第二种:先Coding,然后Unit Test,最后Bug Fix.很显然用了单元测试的比第一种开发方式要好不少. 第三种:就是本文要说的TDD,它的方式和第二种恰恰相反.TDD先设计单元测试,然后再Coding,最后修复Bug.看下图: TDD开发过程可以看成:给制自己制定一个目

一起谈.NET技术,ASP.NET MVC中对Model进行分步验证的解决方法

在我之前的文章:ASP.NET MVC2.0结合WF4.0实现用户多步注册流程中将一个用户的注册分成了四步,而这四个步骤都是在完善一个Model的信息,但是又分页面填写信息的,当时我加上ModelState.IsValid这句验证代码的时候,根本没法通过验证,因为在注册的前面三步,注册用户的Model信息都没填写完整,而ModelState.IsValid是对一个实体的所有属性进行判断验证的.当时很纠结,因为刚接触Asp.net MVC,故没有找到解决方案.这篇文章将给出解决的办法.看下面需要验

一起谈.NET技术,ASP.NET MVC中实现多个按钮提交的几种方法

有时候会遇到这种情况:在一个表单上需要多个按钮来完成不同的功能,比如一个简单的审批功能.   如果是用webform那不需要讨论,但asp.net mvc中一个表单只能提交到一个Action处理,相对比较麻烦点. 方法一:使用客户端脚本 比如我们在View中这样写: 代码 <inputtype="submit"value="审核通过"onclick='this.form.action="<%=Url.Action("Action1&q

ASP.NET MVC中的视图生成简介

在 ASP.NET MVC 中,我们将前端的呈现划分为三个独立的部分来实现,Controller 用来控制用户的操作,View 用来控制呈现的内容,Model 用来表示处理的数据. 从控制器到视图 通常,在 Controller 中,我们定义多个 Action ,每个 Action 的返回类型一般是 ActionResult,在 Action 处理的最后,我们返回对于视图的调用. public ActionResult Index() {    return this.View(); } 默认情

在 Asp.NET MVC 中使用 SignalR 实现推送功能

原文http://www.cnblogs.com/kesalin/archive/2012/11/09/signalr_push.html 在 Asp.NET MVC 中使用 SignalR 实现推送功能 罗朝辉 ( http://www.cnblogs.com/kesalin/ ) CC许可,转载请注明出处   一,简介 Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架.它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户

在ASP.NET MVC中使用“RadioButtonList”和“CheckBoxList”

在<为HtmlHelper添加一个RadioButtonList扩展方法>中我通过对HtmlHelper和HtmlHelper<Model>的扩展使我们可以采用"RadioButtonList"的方式对一组类型为"radio"的<input>元素进行操作.昨天对对此进行了一些改进,并将"CheckBoxList"的功能添加进来.[源代码从这里下载] 一.有何特别之处? 和我的很多文章一样,旨在提供一种大体的解决

在ASP.NET MVC中使用IIS级别的URL Rewrite

原文 在ASP.NET MVC中使用IIS级别的URL Rewrite 大约一年半前,我在博客上写过一系列关于URL Rewrite的文章(2.3.4),把ASP.NET平台上进行URL Rewrit的方式和各自地特点进行了较为详细的描述.应该来说,已经讲的非常具体,可以应对90%的情况.其实IIS Rewrite的原理非常容易理解,进行一些简单的变化和推断之后,便可以得出一些问题的原因和解决方案.现在我们就来看一个真实案例:在ASP.NET MVC中使用IIS级别的URL Rewrite. 在