小编典典

调用Web API 2端点时HTTP 415不支持的媒体类型错误

json

我有一个现有的Web API
2服务,需要修改其中一个方法以将自定义对象作为另一个参数,当前该方法具有一个参数,该参数是来自URL的简单字符串。在将自定义对象添加为参数之后,从.NET
Windows应用程序调用服务时,我现在收到415不支持的媒体类型错误。有趣的是,我可以使用javascript和jquery ajax方法成功调用此方法。

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

该方法既允许POSTGET由于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
API2。我知道路由正在工作,调用已正确路由到该方法,它们不会意外地移到其他地方,所以.NET客户端中缺少什么?任何帮助深表感谢!

-–更新—
我试图创建一个全新的Web
API服务以排除现有服务的任何可能的问题,我创建了一个控制器,该控制器使用单个方法将自定义对象作为参数。然后,我尝试从.NET客户端调用它,并得到相同的错误。我也尝试使用WebClient代替HttpWebRequest,但仍然遇到相同的错误。这也是以前使用Web
API(在Web API 2之前)对我有用的东西。

-–更新—
我还尝试使用Web API 1创建一个新的Web应用程序,当我使用POST调用它时,我的复杂对象参数现在为null。我有另一个运行Web API
1的Web服务,并验证了我仍然可以使用复杂对象成功调用它。无论我的问题是什么,它似乎都是在客户端和服务器之间传递JSON所致。我已经检查了要发送的JSON及其有效信息,对象定义也是客户端和服务器之间的精确匹配,因此服务器应该能够解析JSON。


阅读 265

收藏
2020-07-27

共1个答案

小编典典

解决
了这个问题后,我将头撞在墙上了几天,看来问题出在客户端和服务器之间的内容类型协商上。我用Fiddler来检查来自客户端应用程序的请求详细信息,这是fiddler捕获的原始请求的屏幕截图:

Fiddler捕获来自客户端应用程序的http请求

显然缺少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"

仅此而已,ContentType只需在写入请求主体之前设置属性

我相信这种行为是因为一旦将内容写入主体,然后将其流式传输到被调用的服务端点,则需要在此之前设置与该请求有关的任何其他属性。如果我输入错误或需要更多详细信息,请纠正我。

2020-07-27