web-dev-qa-db-ja.com

Web API 2エンドポイントを呼び出すときのHTTP 415サポートされていないメディアタイプエラー

既存のWeb API 2サービスがあり、カスタムオブジェクトを別のパラメーターとして受け取るようにメソッドの1つを変更する必要があります。現在、このメソッドには、URLからの単純な文字列である1つのパラメーターがあります。カスタムオブジェクトをパラメーターとして追加した後、.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
_

POSTオブジェクトはオプションであるため、このメソッドではGETPagingの両方を使用できます。このメソッドを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 "を削除しました
  • xML応答コンテンツをいくつかの静的JSONで置き換え、要求での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クライアントからそれを呼び出してみましたが、同じエラーが発生しました。また、HttpWebRequestの代わりにWebClientを使用してみましたが、それでも同じエラーが発生します。これは、以前はWeb API(Web API 2より前)でも機能していたものです。

---更新---
POSTを使用してそれを呼び出すと、Web API 1を使用して新しいWebアプリを作成しようとしましたが、複雑なオブジェクトパラメーターがnullになりました。別のWebサービスを実行しています。 Web API 1を実行し、複雑なオブジェクトでも引き続き正常に呼び出すことができることを確認しました。問題が何であれ、クライアントとサーバーの間でJSONが渡されているようです。送信しているJSONとその有効性を確認しました。オブジェクト定義もクライアントとサーバー間で完全に一致するため、サーバーでJSONを解析できるはずです。

38
AK3800

[〜#〜]解決済み[〜#〜]
この問題で2日間壁をぶつけた後、問題はクライアントとサーバー間のコンテンツタイプネゴシエーションに関係しているように見えました。 Fiddlerを使用してクライアントアプリからのリクエストの詳細を確認する方法を詳しく説明します。次は、fiddlerによってキャプチャされた未加工のリクエストのスクリーンショットです。

Fiddler capture of http request from client app

元の投稿のコードサンプルにあるように設定していたにもかかわらず、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プロパティを設定するだけで済みました

この動作は、コンテンツが本文に書き込まれると、呼び出されているサービスエンドポイントにストリーミングされた後、リクエストに関連する他の属性をその前に設定する必要があるためと考えています。私が間違っている場合、またはこれがさらに詳細を必要とする場合は、私を修正してください。

55
AK3800

Web APIエンドポイントを呼び出すときにこの問題が発生し、解決しました。

私の場合、クライアントが本文コンテンツをエンコードする方法に問題がありました。エンコーディングやメディアタイプを指定していませんでした。それらを指定することで解決しました。

エンコードタイプを指定していない、415エラーが発生:

var content = new StringContent(postData);
httpClient.PostAsync(uri, content);

エンコーディングとメディアタイプの指定、成功:

var content = new StringContent(postData, Encoding.UTF8, "application/json");
httpClient.PostAsync(uri, content);
30
James Wierzba

このエラーも発生しました。

ヘッダーに追加Content-Typeapplication/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)
2
Harley