web-dev-qa-db-fra.com

Erreur de type de support HTTP 415 non pris en charge lors de l'appel du point de terminaison Web API 2

J'ai un service Web API 2 existant et j'ai besoin de modifier l'une des méthodes pour prendre un objet personnalisé comme autre paramètre, actuellement la méthode a un paramètre qui est une simple chaîne provenant de l'URL. Après avoir ajouté l'objet personnalisé en tant que paramètre, j'obtiens maintenant une erreur de type de support 415 non pris en charge lors de l'appel du service à partir d'une application Windows .NET. Fait intéressant, je peux appeler cette méthode avec succès en utilisant javascript et la méthode jquery ajax.

La méthode de service Web API 2 ressemble à ceci:

<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

La méthode autorise à la fois POST et GET car l'objet Paging est facultatif. Si j'appelle cette méthode avec une demande GET cela fonctionne.

Et le code client .NET simple appelant le service ressemble à ceci:

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

Le client .NET s'exécute sur le framework 4.5 et le service est sur le framework 4.5.2. L'erreur est renvoyée sur la ligne resp = req.GetResponse(). Certaines choses que j'ai déjà essayées:

  • sur le client, définissez la valeur req.Accept sur "application/xml" ou "text/xml"
  • dans la méthode de service, supprimé la ligne `resp.Content.Headers.ContentType.MediaType =" text/xml "
  • remplacer le contenu de la réponse XML par du JSON statique, a tenté d'éliminer tout problème avec l'envoi de JSON sur la demande et le retour de XML sur la réponse

Jusqu'à présent, je continue d'obtenir la même réponse d'erreur 415, peu importe ce que j'essaie.

J'ai mentionné que cela fonctionne lorsqu'il est appelé à partir de javascript, voici mon appel ajax qui fonctionne:

$.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");
   }
});

Côté service, il n'y a rien d'extraordinaire à faire avec la configuration de l'itinéraire ou quoi que ce soit d'autre, c'est à peu près toute l'API Web prête à l'emploi 2. Je sais que le routage fonctionne, les appels sont correctement acheminés vers la méthode, ils ne vont pas ailleurs de manière inattendue, alors qu'est-ce qui me manque dans le client .NET? Toute aide est très appréciée!

--- MISE À JOUR ---
J'ai essayé de créer un tout nouveau service d'API Web pour exclure tout problème possible avec le service existant, j'ai créé un contrôleur avec une seule méthode qui prend un objet personnalisé comme paramètre. J'ai ensuite essayé d'appeler cela depuis le client .NET et j'ai eu la même erreur. J'ai également essayé d'utiliser WebClient au lieu de HttpWebRequest, mais j'obtiens toujours la même erreur. C'est aussi quelque chose qui fonctionnait auparavant pour moi avec l'API Web (avant l'API Web 2).

--- MISE À JOUR ---
J'ai également essayé de créer une nouvelle application Web à l'aide de l'API Web 1, lorsque j'appelle cela avec un POST mon paramètre d'objet complexe arrive maintenant en null. J'ai un autre service Web exécutant l'API Web 1 et j'ai vérifié que je peux toujours l'appeler avec succès avec des objets complexes. Quel que soit mon problème, il semble que le JSON passe entre le client et le serveur. J'ai vérifié le JSON que j'envoie et sa validité, la définition d'objet est également une correspondance exacte entre le client et le serveur, le JSON doit donc pouvoir être analysé par le serveur.

38
AK3800

[~ # ~] résolu [~ # ~]
Après m'être cogné la tête contre le mur pendant quelques jours avec ce problème, il semblait que le problème avait quelque chose à voir avec la négociation du type de contenu entre le client et le serveur. J'ai approfondi cela en utilisant Fiddler pour vérifier les détails de la demande provenant de l'application cliente, voici une capture d'écran de la demande brute capturée par fiddler:

Fiddler capture of http request from client app

Ce qui manque évidemment, c'est le Content-Type header, même si je le définissais comme on le voit dans l'exemple de code de mon message d'origine. J'ai trouvé étrange que le Content-Type jamais vu, même si je le définissais, j'ai donc jeté un coup d'œil à mon autre code (de travail) appelant un service d'API Web différent, la seule différence était que je me trouvais à définir le req.ContentType propriété avant d'écrire à l'organisme demandeur dans ce cas. J'ai apporté ce changement à ce nouveau code et c'est ainsi que le Content-Type apparaissait maintenant et j'ai obtenu la réponse attendue du service Web. Le nouveau code de mon client .NET ressemble maintenant à ceci:

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"

C'est tout ce que c'était, la propriété ContentType devait juste être définie avant d'écrire dans le corps de la requête

Je crois que ce comportement est dû au fait qu'une fois le contenu écrit dans le corps, il est transmis au point de terminaison de service appelé, tout autre attribut relatif à la demande doit être défini avant cela. Veuillez me corriger si je me trompe ou si cela nécessite plus de détails.

55
AK3800

J'ai rencontré ce problème lors de l'appel de mon point de terminaison d'API Web et je l'ai résolu.

Dans mon cas, c'était un problème dans la façon dont le client encodait le contenu du corps. Je ne spécifiais pas l'encodage ou le type de support. Leur spécification l'a résolu.

Ne spécifie pas le type de codage, a provoqué une erreur 415:

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

Spécification de l'encodage et du type de média, succès:

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

J'ai également rencontré cette erreur.

J'ajoute dans l'en-tête Content-Type: application/json. Après le changement, mes soumissions réussissent!

6

J'essayais d'écrire un code qui fonctionnerait à la fois sur Mac et Windows. Le code fonctionnait bien sous Windows, mais donnait la réponse sous la forme 'Unsupported Media Type' sur Mac. Voici le code que j'ai utilisé et la ligne suivante a également fait fonctionner le code sur Mac:

Request.AddHeader "Content-Type", "application/json"

Voici l'extrait de mon 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)
2
Harley