Js+MVC~公用API的设计,返回jsonp后使ajax的error属性生效!

相关知识说明

  项目用公用的API事实上就是其它子项目,包括非子项目需要从这个项目中得到一个公用的信息,这种产生信息的接口我们称为公用的API(application program interface),例如:一个A网站,它有用户模块,产品模块,订单模块,帮助中心模组成,而在A网站旗下有它的A论坛,A社区,A微博等,而这些子网站的用户来源是从A网站来的,而如果在子网站中希望得到用户的详细信息,就需要我们在主网站提供一个开放的API,而这个API是如果通过GET请求直接访问的,这是正常的,但如果在A微博中需要异步得到信息,即以ajax方式得到信息,直接访问是不可以的,必须使用jsonp的方式!而对于jsonp来说,如果主网站的接口出现问题了,在默认情况下是不能通知到子网站的,这是jsonp自己的事,而jquery也提供了应对的方法,那就是jquery.jsonp插件,可以在这里下载

说干就干

对于MVC开发环境来说,在视图渲染上提供了对html,javascript,text,json等渲染方式,如果jsonp来说,mvc本身并没有提供,事实上jsonp只是向页面输出json文本信息的变种,我们完全可以自己去伪造一个,当然把它封装的好一些就是要继承JsonResult,并在渲染方法ExecuteResult作一个文章就可以了,看代码:

 1   /// <summary>
 2     /// 返回jsonp上下文
 3     /// </summary>
 4     public class JsonpResult : JsonResult
 5     {
 6         const string CALLBACKNAME = "callback";
 7         /// <summary>
 8         /// 复写渲染视图方法
 9         /// </summary>
10         /// <param name="context"></param>
11         public override void ExecuteResult(ControllerContext context)
12         {
13             if (context == null)
14             {
15                 throw new ArgumentNullException("当前请求上下文出错");
16             }
17             if ((JsonRequestBehavior == JsonRequestBehavior.DenyGet)
18                 && String.Equals(context.HttpContext.Request.HttpMethod, "GET"))
19             {
20                 throw new InvalidOperationException("Jsonp只能是GET请求");
21             }
22             var response = context.HttpContext.Response;
23             if (!String.IsNullOrEmpty(ContentType))
24             {
25                 response.ContentType = ContentType;
26             }
27             else
28             {
29                 response.ContentType = "application/json";
30             }
31             if (ContentEncoding != null)
32             {
33                 response.ContentEncoding = this.ContentEncoding;
34             }
35             if (Data != null)
36             {
37                 String buffer;
38                 var request = context.HttpContext.Request;
39                 var serializer = new JavaScriptSerializer();
40                 if (request[CALLBACKNAME] != null)
41                     buffer = String.Format("{0}({1})", request[CALLBACKNAME], serializer.Serialize(Data));
42                 else
43                     buffer = serializer.Serialize(Data);
44                 response.Write(buffer);
45             }
46         }
47     }

而对于公用的API来说,我们可以在controller里这样去写:

 1      /// <summary>
 2         /// 跨域API
 3         /// </summary>
 4         /// <returns></returns>
 5         public JsonpResult GetUserAPI(string userID)
 6         {
 7             JsonpResult result = new JsonpResult()
 8             {
 9                 Data = new { name = "zzl", res = true, },
10                 JsonRequestBehavior = JsonRequestBehavior.AllowGet
11             };
12             return result;//反回一个callback(msg)对象
13         }

OK,底层获到公用信息的工作已经完成了,再看一下如何在A微博页面上去调用它:

 1  //跨域调用公用的API,如果希望它相应error事件,需要使用$.jsonp,而不是JQ的$.ajax
 2     function jsonpFun() {
 3         $.ajax({
 4             dataType: 'jsonp', //跨域使用它
 5             jsonp: 'callback', //可以省略,但如果显示声明它,必须是callback,因为在JsonResult里jsonp字符串已经被规定成它了
 6             url: 'http://www.jsonp.com/Common/GetUserAPI',
 7             data: { userID: 1 },
 8             type: 'GET',
 9             success: function (data) {
10                 alert(data.name);
11             },
12             error: function (data) {
13                 alert("获取用户信息失败");
14             }
15         });
16     }

上面的代码应该改为:

 1       $.jsonp({
 2             url: 'http://www.jsonp.com/Common/GetUserAPI?userID=1',
 3             callbackParameter: 'callback',
 4             success: function (data) {
 5                 alert(data.name);
 6             },
 7             error: function (xOptions, textStatus) {
 8                 alert("获取用户信息失败");
 9             }
10         });

 

好了,前面已经说了对于jsonp来说,ajax的error属性是不好使的,我们需要在页面上引用jquery.jonsp这个js插件才行:

1 <script src="http://www.cnblogs.com/Scripts/jquery.jsonp-2.3.0.min.js" type="text/javascript"></script>

OK,我们测试一下吧:

没有问题,信息已经得到了,再看看fiddler所捕获的消息:

我们的URL上自己加上了callback,而这个串是A网站与A微博网站自己规定的,如果您不知道它们的规范,这个请求是会失败的,这是正常的,呵呵。

通过GET请求,直接可以返回你要的字符,这也是正常的,当然实现项目中,我们会在双方进行密文的设计的!

posted @ 2012-12-14 10:30  张占岭  阅读(1429)  评论(3编辑  收藏  举报