json 调用 Web API 2 端点时出现 HTTP 415 不受支持的媒体类型错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34660641/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HTTP 415 unsupported media type error when calling Web API 2 endpoint
提问by AK3800
I have an existing Web API 2 service and need to modify one of the methods to take a custom object as another parameter, currently the method has one parameter which is a simple string coming from the URL. After adding the custom object as a parameter I am now getting a 415 unsupported media type error when calling the service from a .NET windows app. Interestingly, I can successfully call this method using javascript and the jquery ajax method.
我有一个现有的 Web API 2 服务,需要修改其中一个方法以将自定义对象作为另一个参数,目前该方法有一个参数,它是来自 URL 的简单字符串。添加自定义对象作为参数后,我现在在从 .NET Windows 应用程序调用服务时收到 415 unsupported media type 错误。有趣的是,我可以使用 javascript 和 jquery ajax 方法成功调用此方法。
The Web API 2 service method looks like this:
Web API 2 服务方法如下所示:
<HttpPost>
<HttpGet>
<Route("{view}")>
Public Function GetResultsWithView(view As String, pPaging As Paging) As HttpResponseMessage
Dim resp As New HttpResponseMessage
Dim lstrFetchXml As String = String.Empty
Dim lstrResults As String = String.Empty
Try
'... do some work here to generate xml string for the response
'// write xml results to response
resp.Content = New StringContent(lstrResults)
resp.Content.Headers.ContentType.MediaType = "text/xml"
resp.Headers.Add("Status-Message", "Query executed successfully")
resp.StatusCode = HttpStatusCode.OK
Catch ex As Exception
resp.StatusCode = HttpStatusCode.InternalServerError
resp.Headers.Add("Status-Message", String.Format("Error while retrieving results from view {0}: {1}", view, ex.Message))
End Try
Return resp
End Function
The method allows both POSTand GETbecause the Pagingobject is optional. If I call this method with a GETrequest it works.
该方法允许POST并且GET因为Paging对象是可选的。如果我通过GET请求调用此方法,它会起作用。
And the simple .NET client code calling the service looks like this:
调用服务的简单 .NET 客户端代码如下所示:
Dim uri As String = BASE_URI + "fetch/someview"
Dim resp As HttpWebResponse
Dim sr As StreamReader
Dim lstrResponse As String
Dim reqStream As Stream
Dim bytData As Byte()
Dim req As HttpWebRequest = WebRequest.Create(uri)
Dim lstrPagingJSON As String
Dim lPaging As New Paging
Try
lPaging.Page = 1
lPaging.Count = 100
lPaging.PagingCookie = ""
req.Method = "POST"
lstrPagingJSON = JsonSerializer(Of Paging)(lPaging)
bytData = Encoding.UTF8.GetBytes(lstrPagingJSON)
req.ContentLength = bytData.Length
reqStream = req.GetRequestStream()
reqStream.Write(bytData, 0, bytData.Length)
reqStream.Close()
req.ContentType = "application/json"
resp = req.GetResponse()
sr = New StreamReader(resp.GetResponseStream, Encoding.UTF8)
lstrResponse = sr.ReadToEnd
'// do something with the response here
Catch exweb As WebException
txtOutput.AppendText("Error during request: " + exweb.Message)
Catch ex As Exception
txtOutput.AppendText(String.Format("General error during request to {0}: {1}", uri, ex.Message))
End Try
The .NET client is running on the 4.5 framework and the service is on 4.5.2 framework. The error is thrown at the resp = req.GetResponse()line. Some things I tried already:
.NET 客户端在 4.5 框架上运行,服务在 4.5.2 框架上运行。错误是resp = req.GetResponse()在行上抛出的。我已经尝试过的一些事情:
- on the client, set the
req.Acceptvalue to "application/xml" or "text/xml" - in the service method, removed the line `resp.Content.Headers.ContentType.MediaType = "text/xml"
- replace the XML response content with some static JSON, tried to rule out any problems with sending in JSON on the request and getting XML back on the response
- 在客户端,将
req.Accept值设置为“application/xml”或“text/xml” - 在服务方法中,删除了行 `resp.Content.Headers.ContentType.MediaType = "text/xml"
- 用一些静态 JSON 替换 XML 响应内容,试图排除在请求中发送 JSON 和在响应中返回 XML 的任何问题
So far I keep getting the same 415 error response no matter what I try.
到目前为止,无论我尝试什么,我都会收到相同的 415 错误响应。
I mentioned this works when called from javascript, here's my ajax call that is working:
我提到这在从 javascript 调用时有效,这是我的 ajax 调用有效:
$.ajax({
headers: {},
url: "api/fetch/someview",
type: "POST",
data: "{Count:100,Page:1,PagingCookie:\"\"}",
contentType: "application/json; charset=utf-8",
dataType: "xml",
success: function (data) {
alert("call succeeded");
},
failure: function (response) {
alert("call failed");
}
});
On the service side, there is nothing fancy going on with the route config or anything else, it's pretty much all out-of-the-box Web API 2. I know the routing is working, calls are being correctly routed to the method, they're not going somewhere else unexpectedly, so what am I missing in the .NET client? Any help is much appreciated!
在服务方面,路由配置或其他任何东西都没有什么特别之处,几乎都是开箱即用的 Web API 2。我知道路由正在工作,调用被正确路由到方法,他们不会意外地去其他地方,那么我在 .NET 客户端中缺少什么?任何帮助深表感谢!
--- UPDATE ---
I tried to create a completely new Web API service to rule out any possible issues with the existing service, I created a controller with a single method that takes a custom object as the parameter. I then tried calling that from the .NET client and got the same error. I also tried using WebClient instead of HttpWebRequest, but still get the same error. This is also something that previously worked for me with Web API (prior to Web API 2).
--- 更新 ---
我尝试创建一个全新的 Web API 服务以排除现有服务的任何可能问题,我创建了一个控制器,该控制器使用单一方法将自定义对象作为参数。然后我尝试从 .NET 客户端调用它并得到相同的错误。我也尝试使用 WebClient 而不是 HttpWebRequest,但仍然出现相同的错误。这也是我以前使用 Web API(在 Web API 2 之前)工作的东西。
--- UPDATE ---
I also tried creating a new web app using Web API 1, when I call that with a POST my complex object parameter is now coming in null. I have another web service running Web API 1 and verified that I can still call that successfully with complex objects. Whatever my problem is, it appears to be something with the JSON passing between the client and server. I have checked the JSON I'm sending it and its valid, the object definition is also an exact match between the client and server so the JSON should be able to be parsed by the server.
--- 更新 ---
我还尝试使用 Web API 1 创建一个新的 Web 应用程序,当我使用 POST 调用它时,我的复杂对象参数现在为空。我有另一个运行 Web API 1 的 Web 服务,并验证我仍然可以使用复杂对象成功调用它。无论我的问题是什么,它似乎都是在客户端和服务器之间传递 JSON 的问题。我已经检查了我发送的 JSON 及其有效,对象定义也是客户端和服务器之间的完全匹配,因此服务器应该能够解析 JSON。
回答by AK3800
SOLVED
After banging my head on the wall for a couple days with this issue, it was looking like the problem had something to do with the content type negotiation between the client and server. I dug deeper into that using Fiddler to check the request details coming from the client app, here's a screenshot of the raw request as captured by fiddler:
解决
了这个问题在我的头上撞了几天之后,看起来这个问题与客户端和服务器之间的内容类型协商有关。我深入研究了使用 Fiddler 检查来自客户端应用程序的请求详细信息,这是 Fiddler 捕获的原始请求的屏幕截图:
What's obviously missing there is the Content-Typeheader, even though I was setting it as seen in the code sample in my original post. I thought it was strange that the Content-Typenever came through even though I was setting it, so I had another look at my other (working) code calling a different Web API service, the only difference was that I happened to be setting the req.ContentTypeproperty prior to writing to the request body in that case. I made that change to this new code and that did it, the Content-Typewas now showing up and I got the expected success response from the web service. The new code from my .NET client now looks like this:
显然缺少的是Content-Type标题,即使我在原始帖子的代码示例中设置了它。我觉得很奇怪,Content-Type即使我正在设置它也从未通过,所以我再看看我的其他(工作)代码调用不同的 Web API 服务,唯一的区别是我碰巧在req.ContentType之前设置了属性在这种情况下写入请求正文。我对这个新代码进行了更改,并做到了,Content-Type现在显示出来了,我从 Web 服务中得到了预期的成功响应。我的 .NET 客户端的新代码现在看起来像这样:
req.Method = "POST"
req.ContentType = "application/json"
lstrPagingJSON = JsonSerializer(Of Paging)(lPaging)
bytData = Encoding.UTF8.GetBytes(lstrPagingJSON)
req.ContentLength = bytData.Length
reqStream = req.GetRequestStream()
reqStream.Write(bytData, 0, bytData.Length)
reqStream.Close()
'// Content-Type was being set here, causing the problem
'req.ContentType = "application/json"
That's all it was, the ContentTypeproperty just needed to be set prior to writing to the request body
这就是全部,ContentType只需要在写入请求正文之前设置该属性
I believe this behavior is because once content is written to the body it is streamed to the service endpoint being called, any other attributes pertaining to the request need to be set prior to that. Please correct me if I'm wrong or if this needs more detail.
我相信这种行为是因为一旦将内容写入正文,它就会流式传输到被调用的服务端点,需要在此之前设置与请求有关的任何其他属性。如果我错了或者需要更多细节,请纠正我。
回答by James Wierzba
I experienced this issue when calling my web api endpoint and solved it.
我在调用我的 web api 端点时遇到了这个问题并解决了它。
In my case it was an issue in the way the client was encoding the body content. I was not specifying the encoding or media type. Specifying them solved it.
就我而言,这是客户端编码正文内容的方式的问题。我没有指定编码或媒体类型。指定它们解决了它。
Not specifying encoding type, caused 415 error:
未指定编码类型,导致415错误:
var content = new StringContent(postData);
httpClient.PostAsync(uri, content);
Specifying the encoding and media type, success:
指定编码和媒体类型,成功:
var content = new StringContent(postData, Encoding.UTF8, "application/json");
httpClient.PostAsync(uri, content);
回答by Nguy?n Thành Ngh?a
I also experienced this error.
我也遇到过这个错误。
I add into header Content-Type: application/json. Following the change, my submissions succeed!
我添加到标题Content-Type:application/json。更改后,我的提交成功!
回答by Harley
I was trying to write a code that would work on both Mac and Windows. The code was working fine on Windows, but was giving the response as 'Unsupported Media Type'on Mac. Here is the code I used and the following line made the code work on Mac as well:
我试图编写一个可以在 Mac 和 Windows 上运行的代码。该代码在 Windows 上运行良好,但在 Mac 上的响应为“不支持的媒体类型”。这是我使用的代码,下面这行代码也可以在 Mac 上运行:
Request.AddHeader "Content-Type", "application/json"
Here is the snippet of my code:
这是我的代码片段:
Dim Client As New WebClient
Dim Request As New WebRequest
Dim Response As WebResponse
Dim Distance As String
Client.BaseUrl = "http://1.1.1.1:8080/config"
Request.AddHeader "Content-Type", "application/json" *** The line that made the code work on mac
Set Response = Client.Execute(Request)


