我一直在疯狂,试图让jquery.ajax与ie9一起工作。所以我有一个实现CORS的ASP Web API 2 Rest API。所有浏览器的CORS请求都有效。 IE9没有用,因为它使用XDomainRequest。我设法通过为IE9自定义实现ajaxTransport来实现它。
现在GET请求似乎工作正常。但是,当我从IE9发出一个帖子请求时,我收到一个HTTP错误415 - 未报告的媒体类型。
我已经将内容类型设置为:“application / json”,我也尝试过“application / x-www-form-urlencoded”,但是根据我的理解,XDomainRequest并不支持自定义标题的所有内容?有人知道是否需要在WebAPI上设置某些特定内容,还是需要调整请求?
我的请求如下:
$.ajax({
url: hostname + "/api/DDC/Book",
type: "POST",
contentType: "application/json",
data: {
DealID: function () {
return viewModel.get("DealID");
},
LocationID: function () {
return viewModel.get("LocationID");
},
Time: function () {
return viewModel.get("selectedDateTime.Time");
}
}
})
在服务器上我有这个:
[HttpPost("DDC/Book")]
[EnableCors(origins: "*", headers: "*", methods: "POST, GET, OPTIONS, PUT, DELETE")]
public dynamic Post(BookModel model)
{
.........
当我在IE调试器中分析失败的请求时,这是发出的请求标头:
Key Value
Request POST //api/DDC/Book HTTP/1.1
Accept */*
Origin http://myurl.com
Accept-Language hr-HR
Accept-Encoding gzip, deflate
User-Agent Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Host www.somehost.com
Content-Length 55
DNT 1
Connection Keep-Alive
Cache-Control no-cache
我真的失去了所有希望,IE让我变得疯狂(该死的是微软:D),所以任何帮助或建议都非常适合。
编辑:从更多的研究中我发现WebAPI需要内容类型才能工作而XDomainRequest不会发送一个。因此,我看到的唯一解决方案是调整我的webapi,以便在没有设置时使用默认内容类型。虽然不知道如何做到这一点EDIT2:通过将我的所有POST转换为GET来暂时破解我的方式,不知道这有多聪明,但我现在看到它没有更大的问题,所以它会解决问题
答案 0 :(得分:8)
管理自己解决它。正如Ray Nicholus指出的那样,没有Content-Type ASP Web API默认为“application / octet-stream”Content-Type。我需要默认的“application / x-www-form-urlencoded”。
我设法通过编写自己的简单消息处理程序来检查传入的请求“Content-Type”,如果没有任何内容,则会添加一个“application / x-www-form-urlencoded”。
这是代码:
public class DefaultContentTypeMessageHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.Content.Headers.ContentType == null)
request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
var response = await base.SendAsync(request, cancellationToken);
return response;
}
}
更新:
正如罗伯特·基督在下面的评论中所写,我正在为那些之前没有使用过消息处理程序的人提供一些答案:
对于那些乍看之下不了解的人,DelegatingHandlers 允许您在请求/响应对象真正命中之前修改它们 WebAPI框架内部。框架中没有其他东西真的 允许您在模型绑定之前修改传入请求,而不是 实际上写自定义模型粘合剂(eugh)。所以相反,在这里,你 可以嗅出一个null内容类型(由缺点保证 在XDomainRequest规范中,将其更新为xml或json,你将会是 能够正确解析传入的请求。
编写消息处理程序后,需要使用WebAPI进行注册。您可以在WebApiConfig类中执行此操作:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MessageHandlers.Add(new DefaultContentTypeMessageHandler());
// Rest of your code
}
}
答案 1 :(得分:1)
只是为了确认你已经在几个更新中编辑了你的问题:是的,XDomainRequest在请求中不包含Content-Type标头。您现在可能知道,您无法通过此传输设置任何标头。
对于大多数服务器端框架而言,缺少Content-Type特别成问题,因为这意味着他们将无法自动解析响应的内容。在没有Content-Type标头的情况下,RFC 2616表示假定正文是application / octet-stream,在这种情况下可能不是你想要的。因此,在这种情况下,您需要通过对相关请求的预期Content-Type进行硬编码来“手动”解析请求主体服务器端。
我强烈建议您不要简单地将所有POST转换为GET。根据RFC 2616,GET请求应该是“安全的”。通过简单地将所有POST重命名为GET,您不再遵循GET请求的已定义和接受的语义。换句话说,不要这样做。
答案 2 :(得分:1)
Dennis上面的回答使用async,它只在.NET 4.5中可用。对于.NET 4以及可能更低版本,请改用以下委托处理程序:
public class DefaultContentTypeMessageHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.Method == HttpMethod.Post && request.Content.Headers.ContentType == null)
{
request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
}
return base.SendAsync(request, cancellationToken);
}
}
此外,请不要忘记您的USING语句,您需要:
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;