全屏网站怎么做,网站建设个可行性研究,新建网站解析域名,微信小程序制作详细流程一. 简介 前言#xff1a; 跨域问题发生在Javascript发起Ajax调用#xff0c;其根本原因是因为浏览器对于这种请求#xff0c;所给予的权限是较低的#xff0c;通常只允许调用本域中的资源#xff0c; 除非目标服务器明确地告知它允许跨域调用。假设我们页面或者应用已在 …一. 简介 前言 跨域问题发生在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通用--httpProtocolcustomHeadersadd nameAccess-Control-Allow-Origin value* /add nameAccess-Control-Allow-Headers valueAccess-Control-Allow-Origin, AppKey, Authorization /add nameAccess-Control-Allow-Methods valueGET, POST, OPTIONS /add nameAccess-Control-Request-Methods valueGET, POST, OPTIONS //customHeaders/httpProtocol!--允许跨域请求的配置 WebApi和MVC通用 至此结束--modulesremove nameTelemetryCorrelationHttpModule /add nameTelemetryCorrelationHttpModule typeMicrosoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation preConditionintegratedMode,managedHandler /remove nameApplicationInsightsWebTracking /add nameApplicationInsightsWebTracking typeMicrosoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web preConditionmanagedHandler //modulesvalidation validateIntegratedModeConfigurationfalse /handlersremove nameExtensionlessUrlHandler-Integrated-4.0 /remove nameOPTIONSVerbHandler /remove nameTRACEVerbHandler /add nameExtensionlessUrlHandler-Integrated-4.0 path*. verb* typeSystem.Web.Handlers.TransferRequestHandler preConditionintegratedMode,runtimeVersionv4.0 //handlers/system.webServer 2. 分别在MVC和WebApi下的FifthController和CorsController中新建GetUserName方法代码如下 1 /// summary2 /// 方案一的测试接口3 /// http://localhost:2131/api/Fifth/GetUserName?userNameadmin4 /// /summary5 /// param nameuserName/param6 /// returns/returns7 [HttpGet]8 public string GetUserName(string userName)9 {
10 return $WebApiuserName的值为{userName};
11 }
12 /// summary
13 /// 方案一的测试接口
14 /// http://localhost:1912/CorsTest/GetUserName
15 /// /summary
16 /// param nameuserName/param
17 /// returns/returns
18 [HttpGet]
19 public string GetUserName(string userName)
20 {
21 return $MVCuserName的值为{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 /// summary2 /// 方案三MVC默认支持JSONP3 /// 但需要服务器端有类似callback参数接受的然后对返回值进行拼接4 /// /summary5 /// param namecallBack/param6 /// param nameuserName/param7 /// returns/returns8 [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 /// summary4 /// 方法执行后执行5 /// /summary6 /// param namefilterContext/param7 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 /// summary2 /// 方案三自己利用方案一中的原理进行改造3 /// 让方法灵活的支持跨域4 /// /summary5 /// param nameuserName/param6 /// returns/returns7 [MvcCors]8 [HttpGet]9 public string GetInfor2(string userName)
10 {
11 return $MVCuserName的值为{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 /// summary2 /// 原始的JSONP模式返现不支持3 /// /summary4 /// param namecallBack/param5 /// param nameuserName/param6 /// returns/returns7 [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.JsonFormatter, myCallBack);
服务器端代码 1 /// summary2 /// 方案四利用WebApiContrib.Formatting.Jsonp程序集改造支持跨域3 /// /summary4 /// param namecallBack/param5 /// param nameuserName/param6 /// returns/returns7 [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 /// summary2 /// 方案四(改造二)利用过滤器以特性的形式进行作用同时过滤器中进行判断该调用是否属于跨域3 /// 属于的话就对返回值进行跨域的包裹返回不属于的话原样返回。4 /// /summary5 /// param namecallBack/param6 /// param nameuserName/param7 /// returns/returns8 [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 // summary2 /// 扩展3 /// 利用script标签实现JSONP的跨域4 /// 但需要服务器端有类似callback参数接受的然后对返回值进行拼接5 /// /summary6 /// param namecallBack/param7 /// param nameuserName/param8 /// returns/returns9 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?callBackmyCallBackuserNameypf).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 }