在上一篇中简易的搭建了一个Web API 服务,包括前面几篇关于WCF REST服务的文章中,都未能提到如何跨域消费Web API,既然是跨域,自然想到JSONP跨域调用,这有篇文章《说说JSON和JSONP,也许你会豁然开朗,含jQuery用例》很清晰的说明了JSONP是干啥子用的,如何通过jQuery来进行JSONP跨域调用。好,既然这样,那就接上篇,也来试试看新建一个站点来消费我的Web API。
1、新建一个Asp.Net 网站项目,在默认的aspx文件中添加如下代码:
1 $.ajax({ 2 3 async: false, 4 url: "http://localhost:6305/api/Customer/getcustomers?group=2", 5 type: 'GET', 6 dataType: 'jsonp', 7 success: function (data) { 8 var result = JSON.stringify(data); 9 alert(result); 10 }, 11 error: function () { 12 alert('fail'); 13 } 14 });
好,直接按F5进入调试,以为万事OK,没想到,直接给我来了个fail。猜测是jQuery无法处理我Web API 直接返回的Json格式的数据,如何办才好呢,通过关键字 jQuery Jsonp进行搜索,没有任何有用信息,这件输入jsonp web api 进行搜索,还是stackoverflow强大,里面就有这样的一个问答:JSONP with ASP.NET Web API。通过这个问答,知道了JsonpMediaTypeFormatter,当然,问答中给出的JsonpMediaTypeFormatter已经是旧版本的了,通过其他进一步搜索,这里贴出的是4.5环境下的JsonpMediaTypeFormatter:
1 namespace Thinktecture.Web.Http.Formatters 2 { 3 using System; 4 using System.Collections.Generic; 5 using System.IO; 6 using System.Linq; 7 using System.Net.Http.Formatting; 8 using System.Net.Http.Headers; 9 using System.Threading.Tasks; 10 using System.Web; 11 12 namespace API 13 { 14 public class JsonpMediaTypeFormatter : JsonMediaTypeFormatter 15 { 16 17 private string _callbackQueryParamter; 18 19 public JsonpMediaTypeFormatter() 20 { 21 SupportedMediaTypes.Add(DefaultMediaType); 22 SupportedMediaTypes.Add(new MediaTypeWithQualityHeaderValue("text/javascript")); 23 24 MediaTypeMappings.Add(new UriPathExtensionMapping("jsonp", DefaultMediaType)); 25 } 26 27 public string CallbackQueryParameter 28 { 29 get { return _callbackQueryParamter ?? "callback"; } 30 set { _callbackQueryParamter = value; } 31 } 32 33 public override System.Threading.Tasks.Task WriteToStreamAsync(Type type, object value, System.IO.Stream writeStream, System.Net.Http.HttpContent content, System.Net.TransportContext transportContext) 34 { 35 string callback; 36 if (IsJsonpRequest(out callback)) 37 { 38 return Task.Factory.StartNew(() => 39 { 40 var writer = new StreamWriter(writeStream); 41 writer.Write(callback + "("); 42 writer.Flush(); 43 base.WriteToStreamAsync(type, value, writeStream, content, transportContext).Wait(); 44 writer.Write(")"); 45 writer.Flush(); 46 }); 47 } 48 return base.WriteToStreamAsync(type, value, writeStream, content, transportContext); 49 } 50 51 private bool IsJsonpRequest(out string callback) 52 { 53 callback = null; 54 switch (HttpContext.Current.Request.HttpMethod) 55 { 56 case "POST": 57 callback = HttpContext.Current.Request.Form[CallbackQueryParameter]; 58 break; 59 default: 60 callback = HttpContext.Current.Request.QueryString[CallbackQueryParameter]; 61 break; 62 } 63 return !string.IsNullOrEmpty(callback); 64 } 65 } 66 } 67 }
有了JsonpMediaTypeFormatter,只需注册即可。还是在Application_Start事件中注册:
1 protected void Application_Start(object sender, EventArgs e) 2 { 3 RouteTable.Routes.MapHttpRoute("WebApi", "api/{controller}/{action}/{id}", 4 new {id = RouteParameter.Optional}); 5 6 //注册JsonpMediaTypeFormatter 7 var config = GlobalConfiguration.Configuration; 8 config.Formatters.Insert(0, new JsonpMediaTypeFormatter()); 9 10 11 }
重新编译Web API,然后在次在另一个web中测试,总算盼来了想要的结果:
好了,收工完成。