• MVC3/4项目开发中遇到的ajax提交Json数据到后台Controller处理(接收参数)


    注:(原文链接:http://www.cnblogs.com/aehyok/archive/2013/05/18/3085499.html)本文只做收藏,方便以后学习使用

    我这边通过原文的理解做了部分修改,没有使用JsonNet.js这个文件对json数据进行序列化,而是直接使用jquery.js的JSON.stringify()

    前言

      jQuery提供的ajax方法能很方便的实现客户端与服务器的异步交互,在asp.net mvc 框架使用jQuery能很方便地异步获取提交数据,给用户提供更好的体验!
      调用jQuery的ajax方法时,jQuery会根据post或者get协议对参数data进行序列化;

      如果提交的数据使用复杂的json数据,例如:

        {userId:32323,userName:{firstName:"李",lastName:"李大嘴"}}

      那么服务器是无法正常接收到完整的参数,因为jQuery对data的序列化,是使用了键值对拼装的方式; 参数拼装成 userId=32323&userName=object ; userName所指向的对象被序列化成字符串"object"
      如何才能把一个复杂的object对象提交到后台的action参数中呢?

    正文

      第一步解决jQuery对于参数序列化的问题: 引用前台处理Js文件,主要是将Json字符串进行处理将其封装到JsonNet.js文件中(原文使用)

    String.format = function () {
        if (arguments.length == 0)
            return null;
        var str = arguments[0];
        for (var i = 1; i < arguments.length; i++) {
            var re = new RegExp('\\{' + (i - 1) + '\\}', 'gm');
            str = str.replace(re, arguments[i]);
        }
        return str;
    }
    
    String.toSerialize = function (obj) {
        var ransferCharForJavascript = function (s) {
            var newStr = s.replace(
                /[\x26\x27\x3C\x3E\x0D\x0A\x22\x2C\x5C\x00]/g,
                function (c) {
                    ascii = c.charCodeAt(0)
                    return '\\u00' + (ascii < 16 ? '0' + ascii.toString(16) : ascii.toString(16))
                });
            return newStr;
        }
        if (obj == null) {
            return null
        }
        else if (obj.constructor == Array) {
            var builder = [];
            builder.push("[");
            for (var index in obj) {
                if (typeof obj[index] == "function") continue;
                if (index > 0) builder.push(",");
                builder.push(String.toSerialize(obj[index]));
            }
            builder.push("]");
            return builder.join("");
        }
        else if (obj.constructor == Object) {
            var builder = [];
            builder.push("{");
            var index = 0;
            for (var key in obj) {
                if (typeof obj[key] == "function") continue;
                if (index > 0) builder.push(",");
                builder.push(String.format("\"{0}\":{1}", key, String.toSerialize(obj[key])));
                index++;
            }
            builder.push("}");
            return builder.join("");
        }
        else if (obj.constructor == Boolean) {
            return obj.toString();
        }
        else if (obj.constructor == Number) {
            return obj.toString();
        }
        else if (obj.constructor == String) {
            return String.format('"{0}"', ransferCharForJavascript(obj));
        }
        else if (obj.constructor == Date) {
            return String.format('{"__DataType":"Date","__thisue":{0}}', obj.getTime() - (new Date(1970, 0, 1, 0, 0, 0)).getTime());
        }
        else if (this.toString != undefined) {
            return String.toSerialize(obj);
        }
    }
    

     第二步在页面定义两个按钮事件,并在按钮事件JavaScrpit中进行调用(这一步可以根据实际情况作适当的修改)

    @{
        ViewBag.Title = "主页";
    }
        <script src="@Url.Content("~/Scripts/JsonNet.js")" type="text/javascript"></script>
        <script type="text/javascript">
            function Test() {
                var data={UserId:"11",UserName:"2211"};
                $.post("../Home/Test", { User: String.toSerialize(data) }, function (data) { alert(String.toSerialize(data)); });
            }
    
            function TestList() {
                var data = [
                    { UserId: "11", UserName: { FirstName: "323", LastName: "2323" }, Keys: ["xiaoming", "xiaohong"] },
                    { UserId: "22", UserName: { FirstName: "323", LastName: "2323" }, Keys: ["xiaoming", "xiaohong"] },
                    { UserId: "33", UserName: { FirstName: "323", LastName: "2323" }, Keys: ["xiaoming", "xiaohong"] }
                ];
                $.post("../Home/TestList", { User: String.toSerialize(data) }, function (data) { alert(String.toSerialize(data)); });
            }
        </script>
    <h2>@ViewBag.Message</h2>
    <p>
        若要了解有关 ASP.NET MVC 的更多信息,请访问 <a href="http://asp.net/mvc" title="ASP.NET MVC 网站">http://asp.net/mvc</a>。
    </p>
    <input type="button" value="testList" onclick="TestList()" />
    <input type="button" value=test onclick="Test()" />
    

     这一步如果引入的是原文的js则是使用String.toSerialize(data),否则使用jquery自带的JSON.stringify(data);

    第三步 在后台控制器要使用Json专类来处理,所以要专门下载类库文件进行引用http://json.codeplex.com

    下载后解压

    各个.net FrameWork的版本文件都有只需要在项目中引用对应的版本即可,这个文件在vs2012里面已经集成直接引用就好了

    第四步(这一部分很重要) 就是编写针对Json处理的自动绑定Model, 这个步骤需要引入刚才那个Newtonsoft.Json的命名空间;

    using Newtonsoft.Json.Linq;
    using Newtonsoft.Json;
    

    之前有一篇简单的请求参数绑定http://www.cnblogs.com/aehyok/archive/2013/05/01/3052697.html

    namespace MvcApplication3.Helper
    {
        public class JsonBinder<T> : IModelBinder
        {
            public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
            {
                //从请求中获取提交的参数数据 
                var json = controllerContext.HttpContext.Request.Form[bindingContext.ModelName] as string;
                //提交参数是对象 
                if (json.StartsWith("{") && json.EndsWith("}"))
                {
                    JObject jsonBody = JObject.Parse(json);
                    JsonSerializer js = new JsonSerializer();
                    object obj = js.Deserialize(jsonBody.CreateReader(), typeof(T));
                    return obj;
                }
                //提交参数是数组 
                if (json.StartsWith("[") && json.EndsWith("]"))
                {
                    IList<T> list = new List<T>();
                    JArray jsonRsp = JArray.Parse(json);
                    if (jsonRsp != null)
                    {
                        for (int i = 0; i < jsonRsp.Count; i++)
                        {
                            JsonSerializer js = new JsonSerializer();
                            try
                            {
                                object obj = js.Deserialize(jsonRsp[i].CreateReader(), typeof(T));
                                list.Add((T)obj);
                            }
                            catch (Exception e)
                            {
                                throw e;
                            }
                        }
                    }
                    return list;
                }
                return null;
            }
        }
    }
    

     提交的Json可以为单个对象实体类,也可以为实体类的数组List<T>,或者是嵌套的都可以。

    //[JsonObject]
            public class UserInfo
            {
                public string UserId{get;set;}
    
                public UserName UserName{get;set;}
                public List<string> keys { get; set; }
    
            }
            public class UserName
            {
                public string FirstName { get; set; }
                public string LastName { get; set; }
            }
    
            [HttpPost]
            public ActionResult TestList([ModelBinder(typeof(JsonBinder<UserInfo>))]List<UserInfo> User)
            {
                List<UserInfo> list = User;
                return Json(list, JsonRequestBehavior.AllowGet);
            }
    
            [HttpPost]
            public ActionResult Test([ModelBinder(typeof(JsonBinder<UserInfo>))]UserInfo User)
            {
                UserInfo Userinfo = User;
                return Json(User, JsonRequestBehavior.AllowGet);
            }
    

     定义了两个简单的实体类并进行关联和上面通过jQuery Ajax提交过来的Json数据格式一致。
    主要是通过实现了IModelBinder进行参数化绑定即可。

    示例代码下载地址http://url.cn/HRz2JC

    最后感谢作者:aehyok

  • 相关阅读:
    摩托罗拉SE4500 德州仪器TI Omap37xx/AM3715/DM3730/AM3530 wince6.0/Windows Mobile 6.5平台 二维软解调试记录及相关解释
    摩托罗拉SE4500 三星 S3C6410 Wince6.0平台软解码调试记录以及驱动相关问题解释
    MSM8909+Android5.1.1之系统烧录
    PIC16F914SEG脚中电路图注意事项
    PIC16F914ADC模块采集数据转换
    PIC914AD模块使用记录
    PIC914 LCDCON液晶控制寄存器用法
    PIC914SEG设置方法
    示波器用法
    检测单片机是否启动
  • 原文地址:https://www.cnblogs.com/huaku/p/3120546.html
Copyright © 2020-2023  润新知