最近在新公司的项目里面经常用到JQuery的getJSON方法和后台程序进行交互,所以特意来总结一下,以备以后的项目的需要。
jQuery中常用getJSON来调用并获取远程的JSON字符串,将其转换为JSON对象,如果成功,则执行回调函数。原型如下:
jQuery.getJSON( url, [data], [callback] )
url:必需 规定将请求发送的哪个 URL
data : (可选) 规定连同请求发送到服务器的key/value数据
callback: (可选) 载入数据成功时的回调函数

例如:

function LoginSubmit(memberDomain) { 
  
    if (document.getElementById("Account").value == "" || document.getElementById("Password").value == "") { 
  
        alert("用户名或密码不能为空?"); 
  
    } else { 
  
        $.getJSON(memberDomain + "/Login/LoginIndex?jsoncallback=?", { 
  
            account: document.getElementById("Account").value, 
  
            password: document.getElementById("Password").value, 
  
            rnum: Math.random() 
  
        }, function (result) { 
  
            if (result.IsSuccess) { 
  
                loginPanelInit(memberDomain); 
  
            } 
  
            else { 
  
                alert("登录不成功!"); 
  
            } 
  
        }); 
  
    } 
  
}


上面getJSON url部分的memberDomain表示域名,getJSON支持跨域调用,Login表示ASP.NET MVC里面控制器Controller的名字,LoginIndex表示Action的名字.URL后面跟的jsoncallback=?表示该请求是JQuery的JSONP请求.

JQuery官方的网站对getJSON方法的英文解释说明了这一点。
If the URL includes the string "callback=?" (or similar, as defined by the server-side API), the request is treated as JSONP instead. See the discussion of the jsonp data type in $.ajax() for more details.

JSONP即JSON with Padding。由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源。如果要进行跨域请求,我们可以通过使用html的script标记来进行跨域请求,并在响应中返回要执行的script代码,其中可以直接使用JSON传递javascript对象。这种跨域的通讯方式称为JSONP。
很明显,JSONP是一种脚本注入(Script Injection)行为,需要特别注意其安全性。

jQuery对JSONP请求的封装方式很值得提倡:

$.getJSON(url, params + "&jsoncallback=?", function(json){ 
  
    /* do something */ 
  
});



用jsoncallback作为服务器端支持的标准jsonp参数,而每次执行这个方法都会用时间戳生成一个唯一的全局函数名,替换这个“?”,这个细节被封装到黑盒里,使用者不必了解,可以像普通的ajax请求一样,用匿名的回调函数作为最末尾的参数(这是jquery强调的风格),这种语法糖(syntactic sugar)的作用绝对不仅仅是让前端开发人员可以偷懒而已,对代码的可读性,兼容性和今后的维护都有好处。


Jsonp原理:

首先在客户端注册一个callback, 然后把callback的名字传给服务器。

此时,服务器先生成 json 数据。

然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp.

最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。

客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数)

注意:
1.运用JQuery的进行跨域调用时请求地址一定要有 jsoncallback=? ,例如我请求 百度,传一个参数userName=123,应该这样写:http://www.baidu.com?userName=123&jsoncallback=? ,如果我不传参数userName,应该这样写:http://www.baidu.com?jsoncallback=?

2、第二个参数一定要是json格式键/值对的格式。例:{ "email": ""}

3、回调函数,您请求的地址需要返回数据,返回的数据必须是严格的json格式的数据,还需要用参数jsoncallback加小括号包裹jsoncallback(json格式的数据),否则就会出现回调函数不会执行的问题。
如下面控制器返回的数据是就是这种格式jsoncallback(SerializeHelper.JsonSerialize(viewData))。
return Content(string.Format("{0}({1})", jsoncallback, SerializeHelper.JsonSerialize(viewData)), "text/plain", System.Text.Encoding.UTF8);

JQuery跨域调用的后台方法:

public ActionResult LoginIndex(string account, string password) 
  
        { 
  
            string jsoncallback = Request.QueryString["jsoncallback"]; 
  
            bool tag = true; 
  
            loginInfo dto = new loginInfo(); 
  
            dto.Account = account;            
  
            dto.AccountError = ""; 
  
            JsonViewData viewData = new JsonViewData() { IsSuccess = false, ErrorMessage = "登录失败" }; 
  
            password = CryptographyHelper.MD5(CryptographyHelper.MD5(password)); 
  

            MembershipDTO mdto = MembershipBiz.Instance.Login(account, password); 
  

            if (mdto != null) 
  
            { 
  
                if (mdto.Status >= 0) 
  
                { 
  
                    string ip = System.Web.HttpContext.Current.Request.UserHostAddress; 
  
                    MembershipBiz.Instance.LogionUpdate(mdto.MembershipId, ip); 
  
                    UpdateCredit(mdto.MembershipId, ip); 
  
                } 
  
                else 
  
                { 
  
                    dto.AccountError = "该用户不存在"; 
  
                    tag = false; 
  
                    viewData.IsSuccess = false; 
  
                } 
  
            } 
  
            else 
  
            { 
  
                dto.AccountError = "帐号或者密码错误"; 
  
                tag = false; 
  
                viewData.IsSuccess = false; 
  
            } 
  
            if (tag) 
  
            { 
  
                Security.Authentication.Authenticate(account, password, false); 
  
                viewData.IsSuccess = true; 
  
                return Content(string.Format("{0}({1})", jsoncallback, SerializeHelper.JsonSerialize(viewData)), "text/plain", System.Text.Encoding.UTF8); 
  

            } 
  
            else 
  
            { 
  
                viewData.IsSuccess = false; 
  
                return Content(string.Format("{0}({1})", jsoncallback, SerializeHelper.JsonSerialize(viewData)), "text/plain", System.Text.Encoding.UTF8); 
  
            } 
  
        }




JQuery getJSON的等价形式$.ajax()或者JQuery.ajax().这种形式相比$.getJSON形式更加的具体,通过设置不同的参数控制起来更加的灵活。比如在某些特殊情况下可以将请求由异步改为同步async: false,请求的类型可以设置为"post"等。
如下所示:

function GetSupplyNum(id) { 
  
         var childnum = ""; 
  
         jQuery.ajax({ 
  
             type: "get", 
  
             async: false, 
  
             url: "/Default1/GetSupplyCountByCategory", 
  
             data: 'id=' + id + '', 
  
             contentType: "text", 
  
             dataType: "json", 
  
             cache: false, 
  
             success: function (data) { 
  
             childnum = childnum + data; 
  
             } 
  
         }); 
  
         return childnum; 
  
     }