您的位置:首页 > 其它

WebAPI IE8、IE9 跨域问题

2016-10-14 16:55 183 查看
关于WebAPI跨域的问题,网上已经很多了,以下方案可以解决很多跨域问题,但是都不支持IE8、IE9浏览器,JSONP也只能支持Get请求

通过dll配置 Install-Package Microsoft.AspNet.WebApi.Cors

配置 Web.config

IE8,IE9跨域是通过XDomainRequest这个对象去实现,和XMLHttpRequest类似,可以参考下面文档

https://msdn.microsoft.com/zh-cn/library/dd573303(v=vs.85).aspx

使用jQuery.ajax的基础上,在jQuery下面再引用

https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest/blob/master/jQuery.XDomainRequest.js

这样IE8、IE9跨域成功了

public Response<string> Post()
{
Response<string> rs = new Response<string>
{
head = new ResponseHeader { errcode = 0, errmessage = "post" },
data = "hello"
};
return rs;
}


这样IE8、IE9跨域失败了

public Response<string> Post(Request<Message> request)
{
Response<string> rs = new Response<string>
{
head = new ResponseHeader { errcode = 0, errmessage = "post" },
data = request.data.content
};
return rs;
}


后来通过排查,有对象形参的WebAPI就会遇到反序列化问题,(IE8,IE9)转换为request对象的時候报错

试了很多次,前端帶不过來Content-Type,就想到了用參数传递到后端,也修改了jQuery.XDOmainRequest.js这个文件

/*!
* jQuery-ajaxTransport-XDomainRequest - v1.0.4 - 2015-03-05
* https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest * Copyright (c) 2015 Jason Moon (@JSONMOON)
* Licensed MIT (/blob/master/LICENSE.txt)
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as anonymous module.
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals.
factory(jQuery);
}
}(function ($) {

// Only continue if we're on IE8/IE9 with jQuery 1.5+ (contains the ajaxTransport function)
if ($.support.cors || !$.ajaxTransport || !window.XDomainRequest) {
return $;
}

var httpRegEx = /^(https?:)?\/\//i;
var getOrPostRegEx = /^get|post$/i;
var sameSchemeRegEx = new RegExp('^(\/\/|' + location.protocol + ')', 'i');

// ajaxTransport exists in jQuery 1.5+
$.ajaxTransport('* text html xml json', function (options, userOptions, jqXHR) {

// Only continue if the request is: asynchronous, uses GET or POST method, has HTTP or HTTPS protocol, and has the same scheme as the calling page
if (!options.crossDomain || !options.async || !getOrPostRegEx.test(options.type) || !httpRegEx.test(options.url) || !sameSchemeRegEx.test(options.url)) {
return;
}

var xdr = null;

return {
send: function (headers, complete) {
var postData = '';
var userType = (userOptions.dataType || '').toLowerCase();

xdr = new XDomainRequest();
if (/^\d+$/.test(userOptions.timeout)) {
xdr.timeout = userOptions.timeout;
}

xdr.ontimeout = function () {
complete(500, 'timeout');
};

xdr.onload = function () {
var allResponseHeaders = 'Content-Length: ' + xdr.responseText.length + '\r\nContent-Type: ' + xdr.contentType;
var status = {
code: 200,
message: 'success'
};
var responses = {
text: xdr.responseText
};
try {
if (userType === 'html' || /text\/html/i.test(xdr.contentType)) {
responses.html = xdr.responseText;
} else if (userType === 'json' || (userType !== 'text' && /\/json/i.test(xdr.contentType))) {
try {
responses.json = $.parseJSON(xdr.responseText);
} catch (e) {
status.code = 500;
status.message = 'parseerror';
//throw 'Invalid JSON: ' + xdr.responseText;
}
} else if (userType === 'xml' || (userType !== 'text' && /\/xml/i.test(xdr.contentType))) {
var doc = new ActiveXObject('Microsoft.XMLDOM');
doc.async = false;
try {
doc.loadXML(xdr.responseText);
} catch (e) {
doc = undefined;
}
if (!doc || !doc.documentElement || doc.getElementsByTagName('parsererror').length) {
status.code = 500;
status.message = 'parseerror';
throw 'Invalid XML: ' + xdr.responseText;
}
responses.xml = doc;
}
} catch (parseMessage) {
throw parseMessage;
} finally {
complete(status.code, status.message, responses, allResponseHeaders);
}
};

// set an empty handler for 'onprogress' so requests don't get aborted
xdr.onprogress = function () { };
xdr.onerror = function () {
complete(500, 'error', {
text: xdr.responseText
});
};

if (userOptions.data) {
postData = ($.type(userOptions.data) === 'string') ? userOptions.data : $.param(userOptions.data);
}
if (options.contentType && options.contentType.length > 0) {
if (options.url.indexOf('?') > -1) {
options.url = options.url + '&_contentType=' + options.contentType;
} else {
options.url = options.url + '?_contentType=' + options.contentType;
}
}
xdr.open(options.type, options.url);
xdr.send(postData);
},
abort: function () {
if (xdr) {
xdr.abort();
}
}
};
});

return $;

}));


jQuery.XDomainRequest.js



加上消息处理就可以解决

public class CrossDomainFixIEHandler : DelegatingHandler
{
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (request.Method == HttpMethod.Options)
{
HttpResponseMessage response = request.CreateResponse<string>(HttpStatusCode.OK, null);
TaskCompletionSource<HttpResponseMessage> tcs = new TaskCompletionSource<HttpResponseMessage>();
tcs.SetResult(response);
return tcs.Task;
}
if (request.Content.Headers.ContentType == null || string.IsNullOrWhiteSpace(request.Content.Headers.ContentType.MediaType))
{
string contentType = this.GetContentType(string.Concat(request.RequestUri.Query, "&"));
if (string.IsNullOrWhiteSpace(contentType))
{
contentType = "application/json";
}
request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType);
}
return base.SendAsync(request, cancellationToken);
}

/// <summary>
/// 獲取ContentType
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
private string GetContentType(string source)
{
if (string.IsNullOrWhiteSpace(source))
{
return string.Empty;
}
Regex regex = new Regex("[&?]_contentType=(?<contentType>(.*?))&", RegexOptions.IgnoreCase);
Match match = regex.Match(source);
if (match.Success)
{
return match.Groups["contentType"].Value;
}
else
{
return string.Empty;
}
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: