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.
The Web API 2 service method looks like this:
<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 POST
and GET
because the Paging
object is optional. If I call this method with a GET
request it works.
And the simple .NET client code calling the service looks like this:
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:
req.Accept
value to "application/xml" or "text/xml"So far I keep getting the same 415 error response no matter what I try.
I mentioned this works when called from javascript, here's my ajax call that is working:
$.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!
--- 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).
--- 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.
Fixing 415 Unsupported Media Type errorsEnsure that you are sending the proper Content-Type header value. Verify that your server is able to process the value defined in the Content-Type header. Check the Accept header to verify what the server is actually willing to process.
The HTTP 415 Unsupported Media Type client error response code indicates that the server refuses to accept the request because the payload format is in an unsupported format. The format problem might be due to the request's indicated Content-Type or Content-Encoding , or as a result of inspecting the data directly.
You need to set the content-type in postman as JSON (application/json). Go to the body inside your POST request, there you will find the raw option. Right next to it, there will be a drop down, select JSON (application. json).
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:
What's obviously missing there is the Content-Type
header, even though I was setting it as seen in the code sample in my original post. I thought it was strange that the Content-Type
never 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.ContentType
property prior to writing to the request body in that case. I made that change to this new code and that did it, the Content-Type
was 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:
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 ContentType
property just needed to be set prior to writing to the request body
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With