日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第十八节:跨域请求的解决方案和WebApi特有的处理方式

發布時間:2023/12/10 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第十八节:跨域请求的解决方案和WebApi特有的处理方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一. 簡介

前言:?跨域問題發生在Javascript發起Ajax調用,其根本原因是因為瀏覽器對于這種請求,所給予的權限是較低的,通常只允許調用本域中的資源,?除非目標服務器明確地告知它允許跨域調用。假設我們頁面或者應用已在 http://www.test1.com 上了,而我們打算從 http://www.test2.com 請求提取數據。?一般情況下,如果我們直接使用 Ajax 來請求將會失敗,瀏覽器也會返回“源不匹配”的錯誤,"跨域"也就以此由來。?

  本節將結合MVC和WebApi兩套框架介紹通用的跨域請求的解決方案、WebApi特有的解決方案、幾種JSONP模式、以及如何讓WebApi也支持JSONP的改造方案。

  下面列舉幾種跨域的情況:

?

二.? Mvc和WebApi通用的模式

  該模式是MVC和WebApi通用的一種處理模式,簡單便捷,不需要額外添加多余的程序集,只需要在WebConfig中進行配置一下即可。

  同時缺點也比較明顯,那就是只能全局配置,配置完后,所有的控制器下的方法都支持跨域了。

1. 代碼配置如下,在?<system.webServer></system.webServer>節點的 最頂 添加如下代碼:

PS:分析下面代碼

  A.?Access-Control-Allow-Origin :代表請求地址,如:" http://localhost:2131, http://localhost:2133" 多個地址之間用逗號隔開,*? 代表運行所有

  B. Access-Control-Allow-headers: 代表表頭

  C. Access-Control-Allow-method: 代表請求方法。如:"GET,PUT,POST,DELETE"

<system.webServer><!--允許跨域請求的配置 WebApi和MVC通用--><httpProtocol><customHeaders><add name="Access-Control-Allow-Origin" value="*" /><add name="Access-Control-Allow-Headers" value="Access-Control-Allow-Origin, AppKey, Authorization" /><add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS" /><add name="Access-Control-Request-Methods" value="GET, POST, OPTIONS" /></customHeaders></httpProtocol><!--允許跨域請求的配置 WebApi和MVC通用 至此結束--><modules><remove name="TelemetryCorrelationHttpModule" /><add name="TelemetryCorrelationHttpModule" type="Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation" preCondition="integratedMode,managedHandler" /><remove name="ApplicationInsightsWebTracking" /><add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" /></modules><validation validateIntegratedModeConfiguration="false" /><handlers><remove name="ExtensionlessUrlHandler-Integrated-4.0" /><remove name="OPTIONSVerbHandler" /><remove name="TRACEVerbHandler" /><add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /></handlers></system.webServer>

2.? 分別在MVC和WebApi下的FifthController和CorsController中新建GetUserName方法,代碼如下:

1 /// <summary>2 /// 方案一的測試接口3 /// http://localhost:2131/api/Fifth/GetUserName?userName=admin4 /// </summary>5 /// <param name="userName"></param>6 /// <returns></returns>7 [HttpGet]8 public string GetUserName(string userName)9 { 10 return $"WebApi:userName的值為{userName}"; 11 } 12 /// <summary> 13 /// 方案一的測試接口 14 /// http://localhost:1912/CorsTest/GetUserName 15 /// </summary> 16 /// <param name="userName"></param> 17 /// <returns></returns> 18 [HttpGet] 19 public string GetUserName(string userName) 20 { 21 return $"MVC:userName的值為{userName}"; 22 }

3. 在一個新項目中進行跨域調用:

1 //1. WebApi 2 $.get("http://localhost:2131/api/Fifth/GetUserName", { userName: "admin" }, function (data) { 3 console.log(data); 4 }); 5 //2. MVC 6 $.get("http://localhost:1912/CorsTest/GetUserName", { userName: "admin" }, function (data) { 7 console.log(data); 8 });

注釋掉webconfig中的代碼配置結果如下:

配置后的結果如下:

?

三. WebApi特有的處理方式

  該模式和上述通用的模式相比較, 最大的好處就是比較靈活,既可以作用于全局,也可以特性的形式作用于Controller,或者直接作用于Action。

  該方案的前提:先通過Nuget添加【Microsoft.AspNet.WebApi.Cors】程序集。

  核心方法:EnableCorsAttribute(string origins, string headers, string methods)

  * 代表允許所有。

  A.origins代表請求地址:" http://localhost:2131, http://localhost:2133" 多個地址之間用逗號隔開

  B.headers代表表頭:

  C.method代表請求方法:"GET,PUT,POST,DELETE"

1. 作用于全局

  在WebApiConfig類中的Register方法中添加:config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

2. 作用于Controller

  (1). 在WebApiConfig類中的Register方法中添加:config.EnableCors();

  (2). 在FifthController控制器上添加特性:[EnableCors("*", "*", "*")]

3. 作用于Action

  (1).?在WebApiConfig類中的Register方法中添加:config.EnableCors();

  (2). 在GetUserName2方法上添加特性:[EnableCors("*", "*", "*")]

部分代碼如下圖:

代碼測試:分別進行上面1,2,3的代碼配置,測試三次,結果如下,均實現了跨域。

1 $.get("http://localhost:2131/api/Fifth/GetUserName2", { userName: "admin" }, function (data) { 2 console.log(data); 3 });

結果:

?

?

四. MVC下JSONP的幾種寫法

?1. JSON和JSONP的區別

① json格式:
?{
  "id":123,
  "name":"ypf"
?}
② jsonp格式:在json外面包了一層
callback({
  "id":123,
  "name":"ypf"
?})
其中callback取決于url傳到后臺是什么,他就叫什么

2. 利用Jquery實現JSONP

注意前端的兩個參數: dataType: "jsonp", jsonp: "myCallBack", 其中myCallBack需要和服務端回掉方法中的參數名相對應,注釋掉這句話默認傳的名稱叫callback

后臺要有一個參數來接受這個包裹的名稱,然后用它把最后的返回值包裹起來以string的形式返回給客戶端,注:數據要進行序列化。

這種方式有個明顯缺點:假設有一天這個接口不需要跨域,要改會普通請求的普通返回形式, 則需要改代碼,就哭了,而且每個接口都要這么對應去寫跨域的寫法,侵入性太強。

服務器端代碼分享:

1 /// <summary>2 /// 方案三:MVC默認支持JSONP3 /// 但需要服務器端有類似callback參數接受的,然后對返回值進行拼接4 /// </summary>5 /// <param name="callBack"></param>6 /// <param name="userName"></param>7 /// <returns></returns>8 [HttpGet]9 public dynamic GetInfor(string myCallBack, string userName) 10 { 11 var data = new 12 { 13 id = userName + "001", 14 userName = userName 15 }; 16 JavaScriptSerializer js = new JavaScriptSerializer(); 17 string xjs = js.Serialize(data); 18 return Content($"{myCallBack}({xjs})"); 19 20 //或者直接返回字符串 21 //return $"{myCallBack}({xjs})"; 22 }

JS調用代碼分享:

1         $.ajax({2 url: 'http://localhost:1912/CorsTest/GetInfor',3 type: "get",4 dataType: "jsonp",5 //需要和服務端回掉方法中的參數名相對應6 //注釋掉這句話默認傳的名稱叫callback7 jsonp: "myCallBack", 8 cache: false,9 data: { userName: "ypf" }, 10 success: function (data) { 11 console.log(data); 12 console.log(data.id); 13 console.log(data.userName); 14 } 15 });

結果:

3. 思考:MVC下能否也面向切面的形式實現跨域?

效果:①方法依然常規寫法不需要特意的用跨域的寫法 ②哪個方法想支持跨域,哪個方法不想支持能靈活的控制,不要去改方法內部的代碼。③跨域調用和非跨域調用都能調用

思路1:利用過濾器以特性的形式進行作用,同時過濾器內實現方案一中的代碼,詳見MvcCors過濾器和GetInfor2方法

過濾器代碼

1 public class MvcCors:ActionFilterAttribute2 {3 /// <summary>4 /// 方法執行后執行5 /// </summary>6 /// <param name="filterContext"></param>7 public override void OnActionExecuted(ActionExecutedContext filterContext)8 {9 HttpContext.Current.Response.Headers.Add("Access-Control-Allow-Origin", "*"); 10 HttpContext.Current.Response.Headers.Add("Access-Control-Allow-Headers", "x-requested-with,content-type,requesttype,Token"); 11 HttpContext.Current.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET"); 12 } 13 }

GetInfor2方法

1 /// <summary>2 /// 方案三:自己利用方案一中的原理進行改造3 /// 讓方法靈活的支持跨域4 /// </summary>5 /// <param name="userName"></param>6 /// <returns></returns>7 [MvcCors]8 [HttpGet]9 public string GetInfor2(string userName) 10 { 11 return $"MVC:userName的值為{userName}"; 12 }

JS代碼

1 $.get("http://localhost:1912/CorsTest/GetInfor2", { userName: "admin" }, function (data) { 2 console.log(data); 3 });

調用結果

?

思路2:利用過濾器以特性的形式進行作用,同時過濾器中進行判斷該調用是否屬于跨域,屬于的話就對返回值進行跨域的包裹返回,不屬于的話,原樣返回。(MVC版暫未實現,WebApi版詳見下面)

繼續思考:重寫ContentResult,在重寫里面判斷,如果屬于跨域請求,返回值進行跨域的返回,如果不是跨域請求,正常返回 (暫未實現)

?

五. WebApi下JSONP的改造

前言:WebApi默認不支持JSONP, 這里我們需要對其進行改造

測試不支持的代碼

1 /// <summary>2 /// 原始的JSONP模式,返現不支持3 /// </summary>4 /// <param name="callBack"></param>5 /// <param name="userName"></param>6 /// <returns></returns>7 [HttpGet]8 9 public dynamic GetInfor(string myCallBack, string userName) 10 { 11 var data = new 12 { 13 id = userName + "001", 14 userName = userName 15 }; 16 JavaScriptSerializer js = new JavaScriptSerializer(); 17 string xjs = js.Serialize(data); 18 19 return $"{myCallBack}({xjs})"; 20 }

1 $.ajax({2 url: 'http://localhost:1912/CorsTest/GetInfor3',3 type: "get",4 dataType: "jsonp",5 //需要和服務端回掉方法中的參數名相對應6 //注釋掉這句話默認傳的名稱叫callback7 jsonp: "myCallBack",8 cache: false,9 data: { userName: "ypf" }, 10 success: function (data) { 11 console.log(data); 12 console.log(data.id); 13 console.log(data.userName); 14 } 15 });

改造一:

a. 通過Nuget安裝程序集:WebApiContrib.Formatting.Jsonp.

b. 在Global文件中進行配置

//允許JSON的配置(注意前端傳過來的名字必須要為myCallBack)

GlobalConfiguration.Configuration.AddJsonpFormatter(GlobalConfiguration.Configuration.Formatters.JsonForma??tter, "myCallBack");

服務器端代碼:

1 /// <summary>2 /// 方案四:利用WebApiContrib.Formatting.Jsonp程序集改造支持跨域3 /// </summary>4 /// <param name="callBack"></param>5 /// <param name="userName"></param>6 /// <returns></returns>7 [HttpGet]8 9 public dynamic GetInfor2(string userName) 10 { 11 var data = new 12 { 13 id = userName + "001", 14 userName = userName 15 }; 16 JavaScriptSerializer js = new JavaScriptSerializer(); 17 string xjs = js.Serialize(data); 18 return $"{xjs}"; 19 }

前端JS代碼:

$.ajax({url: 'http://localhost:2131/api/Fifth/GetInfor2',type: "get",dataType: "jsonp",//需要和服務端回掉方法中的參數名相對應//注釋掉這句話默認傳的名稱叫callbackjsonp: "myCallBack",cache: false,data: { userName: "ypf" },success: function (data) {console.log(data);var jdata = JSON.parse(data);console.log(jdata.id);console.log(jdata.userName);}});

測試結果:?

改造二:

  利用上述MVC中的思路:利用過濾器以特性的形式進行作用,同時過濾器中進行判斷該調用是否屬于跨域,屬于的話就對返回值進行跨域的包裹返回,不屬于的話,原樣返回。

過濾器代碼:

1 public class JsonCallbackAttribute:ActionFilterAttribute2 {3 private const string CallbackQueryParameter = "myCallBack";4 public override void OnActionExecuted(HttpActionExecutedContext context)5 {6 var callback = string.Empty;7 if (IsJsonp(out callback))8 {9 var jsonBuilder = new StringBuilder(callback); 10 //將數據包裹jsonp的形式進行返回 11 jsonBuilder.AppendFormat("({0})", context.Response.Content.ReadAsStringAsync().Result); 12 context.Response.Content = new StringContent(jsonBuilder.ToString()); 13 } 14 15 base.OnActionExecuted(context); 16 } 17 18 private bool IsJsonp(out string callback) 19 { 20 callback = HttpContext.Current.Request.QueryString[CallbackQueryParameter]; 21 return !string.IsNullOrEmpty(callback); 22 } 23 }

服務端代碼:

1 /// <summary>2 /// 方案四(改造二):利用過濾器以特性的形式進行作用,同時過濾器中進行判斷該調用是否屬于跨域,3 /// 屬于的話就對返回值進行跨域的包裹返回,不屬于的話,原樣返回。4 /// </summary>5 /// <param name="callBack"></param>6 /// <param name="userName"></param>7 /// <returns></returns>8 [HttpGet]9 [JsonCallback] 10 11 public dynamic GetInfor3(string userName) 12 { 13 var data = new 14 { 15 id = userName + "001", 16 userName = userName 17 }; 18 JavaScriptSerializer js = new JavaScriptSerializer(); 19 string xjs = js.Serialize(data); 20 return $"{xjs}"; 21 }

js調用代碼:

1 $.ajax({2 url: 'http://localhost:2131/api/Fifth/GetInfor3',3 type: "get",4 dataType: "jsonp",5 //需要和服務端回掉方法中的參數名相對應6 //注釋掉這句話默認傳的名稱叫callback7 jsonp: "myCallBack",8 cache: false,9 data: { userName: "ypf" }, 10 success: function (data) { 11 console.log(data); 12 var jdata = JSON.parse(data); 13 console.log(jdata.id); 14 console.log(jdata.userName); 15 } 16 });

結果返回:

?

六. 其它

  webSocket 和signalr也是一種跨域方式,mvc下可以利用script標簽實現跨域。?

分享MVC下利用Script標簽實現跨域

服務器端代碼

1 // <summary>2 /// 擴展:3 /// 利用script標簽實現JSONP的跨域4 /// 但需要服務器端有類似callback參數接受的,然后對返回值進行拼接5 /// </summary>6 /// <param name="callBack"></param>7 /// <param name="userName"></param>8 /// <returns></returns>9 public ActionResult GetInfor4(string callBack, string userName) 10 { 11 var data = new 12 { 13 id = userName + "001", 14 userName = userName 15 }; 16 JavaScriptSerializer js = new JavaScriptSerializer(); 17 string xjs = js.Serialize(data); 18 return Content($"{callBack}({xjs})"); 19 20 //或者直接返回字符串 21 //return $"{callback}({xjs})"; 22 }

前端js代碼

1 //1. 原始寫法2 $('<script/>').attr('src', 'http://localhost:1912/CorsTest/GetInfor4?callBack=myCallBack&userName=ypf').appendTo("body")3 //2. 封裝寫法4 CrossData('http://localhost:1912/CorsTest/GetInfor4', { userName: "ypf" }, 'myCallBack');5 6 7      //回調方法8 function myCallBack(data) {9 console.log(data); 10 console.log(data.id); 11 console.log(data.userName); 12 } 13 //封裝跨域方法 14 function CrossData(url, data, callBackMethord) { 15 var queryStr = '?'; 16 for (var key in data) { 17 queryStr += key + '=' + data[key] + '&' 18 } 19 var newUrl = url + queryStr + 'callBack=' + callBackMethord; 20 $('<script/>').attr('src', newUrl).appendTo("body"); 21 }

總結

以上是生活随笔為你收集整理的第十八节:跨域请求的解决方案和WebApi特有的处理方式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 午夜性影院| 欧美日本不卡 | a亚洲精品| 最新视频 - 8mav | 中文字幕人妻丝袜乱一区三区 | 国产精品污 | 日韩欧美二区三区 | 男女一级特黄 | 欧美成人视屏 | av网站免费看 | 日韩欧美中文字幕在线播放 | 亚洲熟妇av日韩熟妇在线 | 欧美在线激情 | 韩国三色电费2024免费吗怎么看 | 欧美日韩久久久久久 | 国产一卡在线 | 黄床大片 | 欧美日韩国产麻豆 | 婷婷视频在线观看 | 精品香蕉99久久久久网站 | 五十路在线观看 | 久久久久久久久久免费视频 | 欧美爱爱爱 | 成人网页在线观看 | 99re在线视频精品 | 麻豆亚洲 | 成年人黄色大片 | 久久国产99 | 日本japanese乳偷乱熟 | 中国国产黄色片 | 自拍偷拍免费 | 欧美在线视频第一页 | 欧美日韩国产网站 | 男人天堂社区 | 亚洲高清中文字幕 | 日本一区二区免费高清视频 | 久久免费在线观看视频 | 尤物精品在线观看 | 欧洲金发美女大战黑人 | aaa在线播放 | 国产精品电影一区 | 木木影院 | 欧美成人国产精品一区二区 | 3d动漫精品啪啪一区二区下载 | 国产4区| 免费在线一级片 | 精品xxxx | 久久国产99 | 色射色| 亚洲香蕉一区 | 天天干天天做天天操 | 国产在线不卡av | 国产精品三区四区 | 粉嫩小泬无遮挡久久久久久 | 国产精品嫩草69影院 | 午夜av成人 | 老师的肉丝玉足夹茎 | 我要操婊| 午夜影院在线观看免费 | 黑人操白妞 | av网站在线看 | 国产av无码专区亚洲av毛网站 | 91美女高潮出水 | 亚洲少妇中文字幕 | 国产一级片av | 日韩羞羞 | 欧美又黑又粗 | 亚洲国产婷婷香蕉久久久久久99 | 日韩一区二区三免费高清在线观看 | 香港黄色网| 亚洲欧美国产精品 | www.婷婷 | 国产女教师一区二区三区 | 卡一卡二视频 | 国产尤物av尤物在线看 | 91免费短视频 | 黑人巨大精品欧美一区免费视频 | 国产免费小视频 | 国产美女流白浆 | 特黄一区二区 | 97se在线视频 | 久久久久久无码午夜精品直播 | 国产一区二区三区视频在线 | 高h免费视频 | 亚洲精品视频三区 | 丝袜 中出 制服 人妻 美腿 | 毛片在线观看视频 | 亚洲精品无码不卡在线播he | 成品人视频ww入口 | 亚洲av永久无码精品国产精品 | 国产精品100 | 波多野结衣黄色 | 福利国产在线 | 黄色免费观看网站 | 黑人巨大精品欧美 | 日韩精品一 | 亚洲国产天堂av | 日本三级免费 | 亚洲最大的av网站 |