在公司常常会用到调用接口的状况,可是一直是用的webservice,我感受真是太笨重了。虽然某些人感受用的很爽、很是爽。好比说:公司在开发的时候须要对接另外一组的接口,而后就只能是指定端口和ip到他的电脑。其中各类问题,他在修改代码,或者电脑不开启,咱们这边都不能进行开发了。我但愿下次能用上apihtml
而后就是,园子里好多api的文章都没有降到跨域的解决方案,演示项目建立成功了,而后就在当前项目的调取成功了api的接口方法。就成功了?逗咱们玩呢?没有错、就是在逗咱们玩。web
这里我已经提早建立好了2个站点,一个api和一个mvc项目。而后分别添加到IIS(这里的iis8),若是不知道怎么添加到iis我就简单描述一下。ajax
打开iis管理器-->网站,右键添加网站-->网站名称随意取名、物理路径选择你项目web所在路径-->而后是应用程序池,最好选择DefaultAppPool-->主机名:取一个本身网站的名字(注意:这里的名字是须要配置host文件的)-->肯定json
而后就是配置host文件了,C:\Windows\System32\Drivers\etc 路径下面的hosts文件,有些电脑是能够直接修改的,若是不能够就复制到桌面修改了再放进去这个文件夹下面便可。配置以下:api
127.0.0.1 myWeb.loca/
127.0.0.1 myApi.loca/跨域
个人web主机名:myWeb.loca/(跟配置iis给本身网站取名是同样的)浏览器
个人api主机名:myApi.loca/(跟配置iis给本身网站取名是同样的)服务器
浏览器访问的时候在前面记得加上:http://myWeb.loca/mvc
接下来我开始实施工程了。上面一系列的配置已经准备好。cors
首先我就要修改webapi的路由,由于默认的是根据参数的传递来决定访问的方法的。这里我设置成mvc的习惯 App_Start-->WebApiConfig.cs
config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } );
而后就是已经写好了的api一个方法
public class ValuesController : ApiController { private LX.EFOPT.BLL.IBLL.IUser_InfoBLL User_InfoBLL = new User_InfoBLL(); // GET api/values public string GetList() { List<LX.EFOPT.Model.User_Info> modelUser_InfoList = User_InfoBLL.GetUser_InfoList(); string jsonList = JsonUtils.SerializeToJson(modelUser_InfoList); return JsonUtils.SerializeToJson(new { code = "1", msg = "success", data = modelUser_InfoList }); }
而后呢,咱们直接在浏览器访问这个api,验证一下咱们的数据是否正确输出,直接访问地址:http://myapi.loca/api/values/GetList
结果显示以下:
哎呀妈呀,好开森!固然,这尚未完呢,我没有逗大家玩。接下来,我在myWeb.loca/ 这个web站点访问api。走你~
一样、我已经在web站点建好了一个user控制器、立刻建一个apitest的页面
<input type="button" id="getlist" value="get数据list" /><br />
function getlist() { var url = "http://myapi.loca/api/values/GetList?callback=?";
console.log("getJSON:start");
$.getJSON(url,
function (data) {
//处理data数据
console.log("getJSON:end");
console.log($.parseJSON(data));
});
}
返回结果:没有执行回调函数
这个问题第一次会很难找到缘由。ajax已经执行并且状态是200,在Network里面还能够看见Response返回的字符串。总之、在$.getJSON的回调函数里面没有执行返回结果。
一、咱们先来一个低成本(低版本)的解决方案。由于此版本只须要Framework 4.0就能够了
咱们在App_Start文件夹下面添加一个JsonCallbackAttribute属性类,让它继承自ActionFilterAttribute。注意看代码,这段代码是根据传过来的参数callback判断的
public class JsonCallbackAttribute : ActionFilterAttribute { private const string CallbackQueryParameter = "callback"; public override void OnActionExecuted(HttpActionExecutedContext context) { var callback = string.Empty; if (IsJsonp(out callback)) { var jsonBuilder = new StringBuilder(callback); jsonBuilder.AppendFormat("({0})", context.Response.Content.ReadAsStringAsync().Result); context.Response.Content = new StringContent(jsonBuilder.ToString()); } base.OnActionExecuted(context); } private bool IsJsonp(out string callback) { callback = HttpContext.Current.Request.QueryString[CallbackQueryParameter]; return !string.IsNullOrEmpty(callback); } }
而后把这个 [JsonCallback]属性加到api方法上面或者控制器上面均可以。
[JsonCallback] public class ValuesController : ApiController //或者 [JsonCallback] public string GetList() { }
接下来咱们再看看执行ajax以后的结果是怎么样呢?
加了[JsonCallback]结果显示:很明显结果显示回调成功了。并且还打印出了json,此刻表明着咱们的方案成功了。哎哟、不错哦~
这个方法须要的成本可就高点了,至少是Framework 4.5以上的版本才行。怕什么。装一个就能够了呗。是、可是通常的服务器上面有4.5的吗?反正咱们的就没有
第一步:仍是在api站点的App_Start文件夹下面添加一个JsonpMediaTypeFormatter类
public class JsonpMediaTypeFormatter : JsonMediaTypeFormatter { public string Callback { get; private set; } public JsonpMediaTypeFormatter(string callback = null) { this.Callback = callback; } public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, System.Net.TransportContext transportContext) { if (string.IsNullOrEmpty(this.Callback)) { return base.WriteToStreamAsync(type, value, writeStream, content, transportContext); } try { this.WriteToStream(type, value, writeStream, content); return Task.FromResult<AsyncVoid>(new AsyncVoid()); } catch (Exception exception) { TaskCompletionSource<AsyncVoid> source = new TaskCompletionSource<AsyncVoid>(); source.SetException(exception); return source.Task; } } private void WriteToStream(Type type, object value, Stream writeStream, HttpContent content) { JsonSerializer serializer = JsonSerializer.Create(this.SerializerSettings); using (StreamWriter streamWriter = new StreamWriter(writeStream, this.SupportedEncodings.First())) using (JsonTextWriter jsonTextWriter = new JsonTextWriter(streamWriter) { CloseOutput = false }) { jsonTextWriter.WriteRaw(this.Callback + "("); serializer.Serialize(jsonTextWriter, value); jsonTextWriter.WriteRaw(")"); } } public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType) { if (request.Method != HttpMethod.Get) { return this; } string callback; if (request.GetQueryNameValuePairs().ToDictionary(pair => pair.Key, pair => pair.Value).TryGetValue("callback", out callback)) { return new JsonpMediaTypeFormatter(callback); } return this; } }
第二步:在Global.asax的Application_Start里面注册一下全局
GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonpMediaTypeFormatter());
其实还有第三第四中解决方案的、只是我测试尚未成功,不知道具体是什么缘由。
这里解决了ajax get获取数据的方法,至于post嘛、客户端本身ajax先提交到本身的Handler.ashx或者控制器嘛。而后用httppost去提交api的接口也是同样的。
谢谢!但愿各位大神能留下一点建议和意见,本人才开始写文章。给点鼓励。
感谢大神的文章
参考文章:http://www.cnblogs.com/artech/p/cors-4-asp-net-web-api-03.html
http://stackoverflow.com/questions/9421312/jsonp-with-asp-net-web-api/18206518#18206518