作为我工作环境的一部分,我们需要支持 IE8,但希望继续推进技术,特别是 CORS。
我在 ie8 中将复杂对象发布到 cors 服务时遇到问题。对象为空。以下是重现的步骤。如果需要,我可以将项目上传到 github。
我创建了一个新的 mvc4 项目。添加了一个 API 控制器。并做了以下改动。
支持预检复杂 cors 调用 (global.asax):
protected void Application_BeginRequest()
{
//This is needed for the preflight message
//https://stackoverflow.com/questions/13624386/handling-cors-preflight-requests-to-asp-net-mvc-actions
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS") { Response.Flush(); }
}
来源:处理对 ASP.NET MVC 操作的 CORS 预检请求
支持 text/plain(ie8 只发送带有 cors 的 text/plain)(global.asax):
protected void Application_Start()
{
//This is needed to support text/plain
HttpConfiguration config = GlobalConfiguration.Configuration;
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
config.Formatters.Remove(config.Formatters.FormUrlEncodedFormatter);
config.Formatters.Remove(config.Formatters.XmlFormatter);
...
}
学分:使用 CORS 在 WebAPI 中将 text/plain 作为复杂对象发布
支持除动词以外的其他函数名称 (put/post/etc) (WebApiConfig.cs)"
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "APICustom",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
...
}
支持 cors (web.config)
<httpProtocol>
<customHeaders>
<!-- cors -->
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
API控制器,我叫PersonController.cs
public class PersonController : ApiController
{
public List<string> Get()
{
List<string> s = new List<string>();
s.Add("s");
s.Add("t");
s.Add("u");
return s;
}
[Serializable()]
public class BaseReply
{
public bool successful = true;
public string error;
}
[Serializable()]
public class UpdateSomethingReply: BaseReply
{
public UpdateSomethingRequest request;
public List<string> stuff = new List<string>();
}
[Serializable()]
public class UpdateSomethingRequest
{
public int hasInt;
public string hasString;
}
//[FromBody]
[HttpPost]
public UpdateSomethingReply UpdateSomething([FromBody] UpdateSomethingRequest request)
{
string body = Request.Content.ReadAsStringAsync().Result;
UpdateSomethingReply reply = new UpdateSomethingReply();
reply.request = request;
reply.stuff.Add("v");
reply.stuff.Add("w");
reply.stuff.Add("x");
return reply;
}
这就是服务的变化程度。所以接下来我创建一个客户端。这也是一个mvc4项目。这里很基本的东西。
用 cors (index.cshtml) 填充 ie8:
<script src="~/Scripts/jQuery.XDomainRequest.js"></script>
来源:https ://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest
调用 cors 服务
$(document).ready(function () {
$.when(
$.ajax({
url: urls.person.UpdateSomething,
type: 'post',
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: JSON.stringify({
hasInt: 1,
hasString: "u"
})
})
)
.fail(function (jqXHR, textStatus, errorThrown) {
})
.done(function (data) {
console.log(JSON.stringify(data));
});
$.when(
$.ajax({
url: urls.person.Get,
dataType: 'json'
})
)
.fail(function (jqXHR, textStatus, errorThrown) {
})
.done(function (data) {
console.log(JSON.stringify(data));
});
$.when(
$.ajax({
url: urls.person.UpdateSomething,
type: 'post',
contentType: "text/plain",
dataType: 'json',
data: JSON.stringify({
hasInt: 1,
hasString: "u"
})
})
)
.fail(function (jqXHR, textStatus, errorThrown) {
})
.done(function (data) {
console.log(JSON.stringify(data));
});
});
正如我之前所说,所有 3 个调用都在 ie8 中完成。但是服务中的请求对象在 ie8 中为空,在 Firefox 中它被填充,即使我强制内容类型为 text/plain
IE8 控制台输出:
{"request":null,"stuff":["v","w","x"],"successful":true,"error":null}
Firefox 控制台输出:
{"request":{"hasInt":1,"hasString":"u"},"stuff":["v","w","x"],"successful":true,"error":null}
2013 年 9 月 25 日更新
我可以确认正在发送正文,但没有被 web api 解析。如果我添加以下 hack,它将按预期返回数据。在 Firefox 中,正文将为空,请求对象已填充。在 ie8 中,body 仍然包含内容,并且请求为空。
[HttpPost]
public UpdateSomethingReply UpdateSomething(UpdateSomethingRequest request)
{
if (request == null && Request.Content.ReadAsStringAsync().Result !="")
{
request = JsonConvert.DeserializeObject<UpdateSomethingRequest>(Request.Content.ReadAsStringAsync().Result);
}
UpdateSomethingReply reply = new UpdateSomethingReply();
reply.request = request;
reply.body=Request.Content.ReadAsStringAsync().Result;
reply.headers = Request.Headers.ToString();
reply.stuff.Add("v");
reply.stuff.Add("w");
reply.stuff.Add("x");
return reply;
}