在公司常常會用到調用接口的狀況,可是一直是用的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