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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章