调用 Web API 2 端点时出现 HTTP 415 不支持的媒体类型错误
HTTP 415 unsupported media type error when calling Web API 2 endpoint
我有一个现有的 Web API 2 服务,需要修改其中一个方法以将自定义对象作为另一个参数,目前该方法有一个参数,它是来自 URL。将自定义对象添加为参数后,从 .NET windows 应用程序调用服务时,我现在收到 415 不受支持的媒体类型错误。有趣的是,我可以使用 javascript 和 jquery ajax 方法成功调用此方法。
Web API2 服务方法如下所示:
<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
该方法允许 POST
和 GET
,因为 Paging
对象是可选的。如果我使用 GET
请求调用此方法,它会起作用。
调用服务的简单 .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
.NET 客户端 运行 在 4.5 框架上,服务在 4.5.2 框架上。在 resp = req.GetResponse()
行抛出错误。有些事情我已经尝试过了:
- 在客户端上,将
req.Accept
值设置为 "application/xml" 或
"text/xml"
- 在服务方法中,删除了行
`resp.Content.Headers.ContentType.MediaType = "text/xml"
- 用一些静态 JSON 替换 XML 响应内容,试图排除在请求中发送 JSON 并返回 XML 的任何问题回应
到目前为止,无论我尝试什么,我都会收到相同的 415 错误响应。
我在从 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");
}
});
在服务方面,路由配置或其他任何东西都没有什么特别的,它几乎都是开箱即用的 Web API 2. 我知道路由正在运行,调用已正确路由到该方法,它们不会意外地转到其他地方,那么我在 .NET 客户端中缺少什么?非常感谢任何帮助!
---更新---
我试图创建一个全新的 Web API 服务以排除现有服务可能存在的任何问题,我创建了一个控制器,该控制器使用一个方法将自定义对象作为参数。然后我尝试从 .NET 客户端调用它并得到同样的错误。我也尝试使用 WebClient 而不是 HttpWebRequest,但仍然出现相同的错误。这也是我以前使用 Web API(在 Web API 2 之前)对我有用的东西。
---更新---
我还尝试使用 Web API 1 创建一个新的 Web 应用程序,当我用 POST 调用它时,我的复杂对象参数现在变为空。我有另一个 Web 服务 运行 Web API 1 并验证我仍然可以使用复杂对象成功调用它。无论我的问题是什么,它似乎与 JSON 在客户端和服务器之间传递有关。我已经检查了我发送的 JSON 并且它有效,对象定义也是客户端和服务器之间的完全匹配,所以 JSON 应该能够被服务器解析。
已解决
在为这个问题苦苦思索了几天之后,看起来这个问题与客户端和服务器之间的内容类型协商有关。我更深入地研究了使用 Fiddler 检查来自客户端应用程序的请求详细信息,这是 fiddler 捕获的原始请求的屏幕截图:
显然缺少的是 Content-Type
header,即使我在原始 post 的代码示例中设置了它。我觉得奇怪的是 Content-Type
即使我设置了它也从未通过,所以我再看看我的其他(工作)代码调用不同的 Web API 服务,唯一的区别是在那种情况下,我碰巧在写入请求 body 之前设置了 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"
就是这样,ContentType
属性 只需要在写入请求之前设置 body
我认为这种行为是因为一旦内容被写入 body,它就会流式传输到被调用的服务端点,与请求相关的任何其他属性都需要在此之前设置。如果我错了或需要更多详细信息,请纠正我。
我在调用我的网络 api 端点时遇到了这个问题并解决了它。
在我的例子中,这是客户端编码正文内容的方式的问题。我没有指定编码或媒体类型。指定它们解决了它。
未指定编码类型,导致 415 错误:
var content = new StringContent(postData);
httpClient.PostAsync(uri, content);
指定编码和媒体类型,成功:
var content = new StringContent(postData, Encoding.UTF8, "application/json");
httpClient.PostAsync(uri, content);
我也遇到过这个错误。
我添加到headerContent-Type
:application/json
。更改后,我的提交成功了!
我正在尝试编写适用于 Mac 和 Windows 的代码。
该代码在 Windows 上运行良好,但在 Mac 上给出的响应为 'Unsupported Media Type'。
这是我使用的代码,下面一行代码也可以在 Mac 上运行:
Request.AddHeader "Content-Type", "application/json"
这是我的代码片段:
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)
在我的例子中是 Asp.Net Core 3.1 API。我将 HTTP GET 方法从 public ActionResult GetValidationRulesForField( GetValidationRulesForFieldDto getValidationRulesForFieldDto)
更改为 public ActionResult GetValidationRulesForField([FromQuery] GetValidationRulesForFieldDto getValidationRulesForFieldDto)
及其工作方式。
我未能在需要一个的 DELETE 上发送正文,结果收到此消息。
以防万一有人遇到我的愚蠢问题:我收到此错误是因为我使用 class/contract 进行请求并且是 HttpGet,我忘记添加 [FromQuery]。
public async Task<IActionResult> EndpointAction([FromQuery] TheContract request)
{
return Ok();
}
// The Contract Type
public class TheContract
{
public int Id;
}
我有一个现有的 Web API 2 服务,需要修改其中一个方法以将自定义对象作为另一个参数,目前该方法有一个参数,它是来自 URL。将自定义对象添加为参数后,从 .NET windows 应用程序调用服务时,我现在收到 415 不受支持的媒体类型错误。有趣的是,我可以使用 javascript 和 jquery ajax 方法成功调用此方法。
Web API2 服务方法如下所示:
<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
该方法允许 POST
和 GET
,因为 Paging
对象是可选的。如果我使用 GET
请求调用此方法,它会起作用。
调用服务的简单 .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
.NET 客户端 运行 在 4.5 框架上,服务在 4.5.2 框架上。在 resp = req.GetResponse()
行抛出错误。有些事情我已经尝试过了:
- 在客户端上,将
req.Accept
值设置为 "application/xml" 或 "text/xml" - 在服务方法中,删除了行 `resp.Content.Headers.ContentType.MediaType = "text/xml"
- 用一些静态 JSON 替换 XML 响应内容,试图排除在请求中发送 JSON 并返回 XML 的任何问题回应
到目前为止,无论我尝试什么,我都会收到相同的 415 错误响应。
我在从 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");
}
});
在服务方面,路由配置或其他任何东西都没有什么特别的,它几乎都是开箱即用的 Web API 2. 我知道路由正在运行,调用已正确路由到该方法,它们不会意外地转到其他地方,那么我在 .NET 客户端中缺少什么?非常感谢任何帮助!
---更新---
我试图创建一个全新的 Web API 服务以排除现有服务可能存在的任何问题,我创建了一个控制器,该控制器使用一个方法将自定义对象作为参数。然后我尝试从 .NET 客户端调用它并得到同样的错误。我也尝试使用 WebClient 而不是 HttpWebRequest,但仍然出现相同的错误。这也是我以前使用 Web API(在 Web API 2 之前)对我有用的东西。
---更新---
我还尝试使用 Web API 1 创建一个新的 Web 应用程序,当我用 POST 调用它时,我的复杂对象参数现在变为空。我有另一个 Web 服务 运行 Web API 1 并验证我仍然可以使用复杂对象成功调用它。无论我的问题是什么,它似乎与 JSON 在客户端和服务器之间传递有关。我已经检查了我发送的 JSON 并且它有效,对象定义也是客户端和服务器之间的完全匹配,所以 JSON 应该能够被服务器解析。
已解决
在为这个问题苦苦思索了几天之后,看起来这个问题与客户端和服务器之间的内容类型协商有关。我更深入地研究了使用 Fiddler 检查来自客户端应用程序的请求详细信息,这是 fiddler 捕获的原始请求的屏幕截图:
显然缺少的是 Content-Type
header,即使我在原始 post 的代码示例中设置了它。我觉得奇怪的是 Content-Type
即使我设置了它也从未通过,所以我再看看我的其他(工作)代码调用不同的 Web API 服务,唯一的区别是在那种情况下,我碰巧在写入请求 body 之前设置了 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"
就是这样,ContentType
属性 只需要在写入请求之前设置 body
我认为这种行为是因为一旦内容被写入 body,它就会流式传输到被调用的服务端点,与请求相关的任何其他属性都需要在此之前设置。如果我错了或需要更多详细信息,请纠正我。
我在调用我的网络 api 端点时遇到了这个问题并解决了它。
在我的例子中,这是客户端编码正文内容的方式的问题。我没有指定编码或媒体类型。指定它们解决了它。
未指定编码类型,导致 415 错误:
var content = new StringContent(postData);
httpClient.PostAsync(uri, content);
指定编码和媒体类型,成功:
var content = new StringContent(postData, Encoding.UTF8, "application/json");
httpClient.PostAsync(uri, content);
我也遇到过这个错误。
我添加到headerContent-Type
:application/json
。更改后,我的提交成功了!
我正在尝试编写适用于 Mac 和 Windows 的代码。 该代码在 Windows 上运行良好,但在 Mac 上给出的响应为 'Unsupported Media Type'。 这是我使用的代码,下面一行代码也可以在 Mac 上运行:
Request.AddHeader "Content-Type", "application/json"
这是我的代码片段:
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)
在我的例子中是 Asp.Net Core 3.1 API。我将 HTTP GET 方法从 public ActionResult GetValidationRulesForField( GetValidationRulesForFieldDto getValidationRulesForFieldDto)
更改为 public ActionResult GetValidationRulesForField([FromQuery] GetValidationRulesForFieldDto getValidationRulesForFieldDto)
及其工作方式。
我未能在需要一个的 DELETE 上发送正文,结果收到此消息。
以防万一有人遇到我的愚蠢问题:我收到此错误是因为我使用 class/contract 进行请求并且是 HttpGet,我忘记添加 [FromQuery]。
public async Task<IActionResult> EndpointAction([FromQuery] TheContract request)
{
return Ok();
}
// The Contract Type
public class TheContract
{
public int Id;
}