引子:电子商务网站支付功能页面往往会有很多信息,对于这些信息的保存,往往是分步完成的,那么使用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.DeserializeReceiverInfo>(bodyText); 
//保存。。。

2、利用自定义的ModelBinder实现

JsonBinder

1 public class JsonBinderT> : 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(); 

8         if (string.IsNullOrEmpty(json)) 
9             return json; 
10 
11         JavaScriptSerializer serializer = new JavaScriptSerializer(); 
12         object jsonData = serializer.DeserializeObject(json); 
13         return serializer.DeserializeT>(json); 
14     } 
15 }

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

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)

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

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

这样我们自定义的IModelBinder就会取代DefaultModelBinder完成数据绑定。

3、直接传递一个Json对象

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

我们试试这种方式。

前端的写法:

var b = { 
    ReceiverId: 5, 
    ReceiverName: "will", 
    Sex: "F", 
    CreateDate: "2011-02-21" 
}; 
$.ajax({ 
    url: "/Home/test1", 
    type: "post", 
    cache: false, 
    data: b, 
    success: function(data) { alert(data.message); }, 
    error: function(xhr, a, b) { alert(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(继承了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 { get; set; } 
我们把JsonValueProviderFactory拿出来放在项目里面,然后在Global.asax里面注册一下,就可以使用了。

protected void Application_Start() 

    AreaRegistration.RegisterAllAreas();

RegisterRoutes(RouteTable.Routes);

ValueProviderFactories.Factories.Add(new JsonValueProviderFactory()); 
}

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

var ReceiverInfo = [ 
            { 
                ReceiverInfoChild: [{ ChildId: "1" }, { ChildId: "11"}], 
                ReceiverId: 5, 
                ReceiverName: "will", 
                Sex: "F", 
                CreateDate: "2011-02-21" 
            }, 
            { 
                ReceiverInfoChild: [{ ChildId: "2" }, { ChildId: "22"}], 
                ReceiverId: 5, 
                ReceiverName: "will", 
                Sex: "F", 
                CreateDate: "2011-02-21" 
            } 
            ]; 
$.ajax({ 
    url: "/Home/test1", 
    type: "post", 
    cache: false, 
    contentType: "application/json;charset=utf-8", 
    data: JSON.stringify(ReceiverInfo), 
    success: function(data) { alert(data.message); }, 
    error: function(xhr, a, b) { alert(xhr.responseText); } 
});

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

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

public ActionResult Test1(ListReceiverInfo> receiverInfo)

看一下调试的结果:

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

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

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

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

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

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

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

ASP.NET MVC中的Json Binding和Validate的更多相关文章

  1. ADO.NET .net core2.0添加json文件并转化成类注入控制器使用 简单了解 iTextSharp实现HTML to PDF ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下 C# AutoMapper 了解一下

    ADO.NET   一.ADO.NET概要 ADO.NET是.NET框架中的重要组件,主要用于完成C#应用程序访问数据库 二.ADO.NET的组成 ①System.Data  → DataTable, ...

  2. ASP.NET MVC中controller和view相互传值的方式

    ASP.NET MVC中Controller向view传值的方式: ViewBag.ViewData.TempData 单个值的传递 Json 匿名类型 ExpandoObject Cookie Vi ...

  3. 如何在 ASP.NET MVC 中集成 AngularJS(3)

    今天来为大家介绍如何在 ASP.NET MVC 中集成 AngularJS 的最后一部分内容. 调试路由表 - HTML 缓存清除 就在我以为示例应用程序完成之后,我意识到,我必须提供两个版本的路由表 ...

  4. 如何在 ASP.NET MVC 中集成 AngularJS(2)

    在如何在 ASP.NET MVC 中集成 AngularJS(1)中,我们介绍了 ASP.NET MVC 捆绑和压缩.应用程序版本自动刷新和工程构建等内容. 下面介绍如何在 ASP.NET MVC 中 ...

  5. 超高性能的json序列化之MVC中使用Json.Net

    先不废话,直接上代码 Asp.net MVC自带Json序列化 /// <summary> /// 加载组件列表 /// </summary> /// <param na ...

  6. Asp.net MVC中提交集合对象,实现Model绑定

    Asp.net MVC中的Model自动绑定功能,方便了我们对于request中的数据的处理, 从客户端的请求数据,自动地以Action方法参数的形式呈现.有时候我们的Action方法中想要接收数组类 ...

  7. Asp.net mvc中的Ajax处理

    在Asp.net MVC中的使用Ajax, 可以使用通用的Jquery提供的ajax方法,也可以使用MVC中的AjaxHelper. 这篇文章不对具体如何使用做详细说明,只对于在使用Ajax中的一些需 ...

  8. Ext.Net学习笔记24:在ASP.NET MVC中使用Ext.Net

    在前面的笔记中已经介绍了如何在ASP.NET WebForm中使用Ext.Net,由于这个系列一直在WebForm中使用,所以并没有涉及到ASP.NET MVC中的用法. 如果你要在ASP.NET M ...

  9. MVC中处理Json和JS中处理Json对象

    MVC中处理Json和JS中处理Json对象 ASP.NET MVC 很好的封装了Json,本文介绍MVC中处理Json和JS中处理Json对象,并提供详细的示例代码供参考. MVC中已经很好的封装了 ...

随机推荐

  1. ArcGIS 10 影像去黑边

    在作卫片执法项目中,需要多个影像叠加截图,这就会出现影像黑边叠加的情况,这时就需要对多幅影像进行处理.主要有两种处理方式:以ArcGIS10.1为例,操作如下:     1.acrtoolbox——& ...

  2. C++RAII

    http://baike.baidu.com/view/1120455.htm?fr=aladdin http://www.cnblogs.com/gnuhpc/archive/2012/12/04/ ...

  3. 转:[Android问答] 开发环境问题集锦

    工欲善其事,必先利其器. 和iOS开发相比,Android的开发环境的版本比较多,随之而来的问题也多.显然,我们不应该浪费宝贵的时间在解决开发环境带来的问题上,为此本文总结了常见的开发环境问题和解决方 ...

  4. JVM学习笔记(三)------内存管理和垃圾回收

    JVM内存组成结构 JVM栈由堆.栈.本地方法栈.方法区等部分组成,结构图如下所示: 1)堆 所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx和-Xms来控制.堆被划分为新生代和旧生 ...

  5. Lunix中文乱码解决方案

    sudo vi /var/lib/locales/supported.d/local#添加下面的中文字符集zh_CN.GBK GBKzh_CN.GB2312 GB2312zh_CN.GB18030 G ...

  6. 面试题_17_to_30_数据类型和 Java 基础面试问题

    17)Java 中应该使用什么数据类型来代表价格?(答案)如果不是特别关心内存和性能的话,使用BigDecimal,否则使用预定义精度的 double 类型. 18)怎么将 byte 转换为 Stri ...

  7. Android开发性能优化大总结

    1.  采用硬件加速,在androidmanifest.xml中application添加android:hardwareAccelerated="true".不过这个需要在and ...

  8. Bitset小结 (POJ2443 & HDU4920)

    学了下bitset用法,从网上找的一些bitset用法,并从中调出一些常用的用法. 构造函数bitset<n> b; b有n位,每位都为0.参数n可以为一个表达式.如bitset<5 ...

  9. bzoj1064

    很巧妙的题 首先有几种情况 1. 有环 2.两点间有多条路径 3.其他 3.显然最简单,最小是3,最大是每个弱联通块中最长链 2.显然,两点间两条路径的差是答案的倍数 1.出现环,那答案一定是其约数, ...

  10. UVa 10054 The Necklace【欧拉回路】

    题意:给出n个珠子,珠子颜色分为两半,分别用1到50之间的数字表示, 现在给出n个珠子分别的颜色,问是否能够串成一个环.即为首尾相连,成为一个回路 判断是否构成一个环,即判断是否为欧拉回路,只需要判断 ...