I'm getting a 406 error when trying to use RestSharp to post a request to a third-party application. I'm new to REST, so I have to admit I didn't even know you could add headers. I tried adding these, but I'm still getting the same issue:
var client = new RestClient(myURL);
RestRequest request = new RestRequest("restAction", Method.POST);
request.AddHeader("Accept", "text/plain");
request.AddHeader("Content-Type", "text/plain");
request.AddParameter("parameter1", param1);
request.AddParameter("parameter2", param2);
var response = client.Execute(request);
From what I've read, this may be dealing with a header named "accept". Is that right?
Any idea what could be going on?
In general in HTTP, when a client makes a request to a server, it tells the server what kinds of formats it's prepared to understand (accept). This list of acceptable formats is what the Accept header is for. If the server can't respond using any of the media types in the Accept header, it will return a 406. Otherwise, it will indicate which media type it chose in the Content-Type header of the response. Putting "*/*" in the Accept header tells the server that the client can handle any response media type.
In my original comment to your question, I said that RestSharp looks like it's including "*" in the Accept header by default, but looking closer I see now that it's actually not. So, if you don't override the Accept header like you've done here, the default header value is "application/json","application/xml","text/json","text/x-json","text/javascript","text/xml", and it appears the server you're talking to doesn't speak any of these media types.
If the server you're working with doesn't speak json or xml, I don't think you can use RestSharp, unless you create your own deserializer. I'm not sure if you can do this from the public API or if you'd have to modify the source yourself and recompile it for you own needs.
Since you're still getting HTTP errors from the server, I would recommend taking RestSharp out of the equation for right now, and just speaking HTTP directly to the server until you actually get a correct response from the server. You can use a tool like Fiddler to make a HTTP requests directly. When you send the request (for now in the debugging stage), send an Accept header of "*/*" to get around the 406. Once you've figured out what media types the server can send back to you, you should change this back to being a media type you know you can read and you know the server can send.
It sounds like the main issue here is really just not knowing the protocol of the server. If there's any documentation on the service you're talking to, I would read that very carefully to figure out what media types it's prepared to respond with and how to craft the URLs that it expects.
Related
For example, ExceptionHandlerMiddleware Middleware code on Github
uses this as:
if (context.Response.HasStarted ||...)
I don't quite get it, how can the web server starts to send response to clients when the request still in the pipeline assuming the ExceptionHandlerMiddleware is the first middleware in the pipeline? Because the request hasn't got out of ExceptionHandlerMiddleware, so it hasn't arrived to the web server, then how could it be that the web server already starts to send responses to client in this scenario?
Any middleware or handler may choose to call WriteAsync (or other similar methods) on the HttpResponse, possibly multiple times.
It's not necessarily possible for all of those writes to just be stored in local buffers, and indeed may not be desirable to just buffer locally. So, sooner or later, those Write calls are going to result in real data being sent over the network.
And, in this concrete example, a handler may have made multiple calls such as the above before it encounters an error condition that causes control to be returned to the ExceptionHandlerMiddleware.
Your specific ExceptionHandlerMiddleware example uses Microsoft.AspNetCore.Http.HttpResponse.HasStarted:
Gets a value indicating whether response headers have been sent to the client.
https://learn.microsoft.com/en-US/dotnet/api/microsoft.aspnetcore.http.httpresponse.hasstarted?view=aspnetcore-5.0
There is also Microsoft.Net.Http.Server.Response.HasStarted:
Indicates if the response status, reason, and headers are prepared to send and can no longer be modified. This is caused by the first write or flush to the response body.
https://learn.microsoft.com/en-US/dotnet/api/microsoft.net.http.server.response.hasstarted?view=aspnetcore-1.1
Each response consis of two parts: Header and Body
These two being sent together to the client, first the headers than the body. So during development, the only opportunity to set any value on the response object that affects the headers is up to the point at which you start sending the body.
As long as you begin sending the body of the response you can no longer change the headers because they are sent as the first part of the response just before the body begins sending.
As usual, in .NET 4.5, I used a HttpClient to send a get request to restful service (a remote server)
However, this time, it returned error 415 - Unsupported Media Type.
I'm expecting the request header including Content-Type = application/json.
And I cannot find a way to set Content-Type correctly.
Anybody has experience for this case or any suggestion will be appreciated!
The code is as below and the httpResponseMessage.RequestMessage.Headers
Updated 1
As I researched, I cannot add a retricted header for Content-Type. Since this is 4.5 implementation. Is this correct?
Updated 2
I tried to add
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
However it returned Cannot send a content-body with this verb-type
I am guessing that your server is not complaining about the invalid content type you requested but about the content type you sent with that request.
That you get
Cannot send a content-body with this verb-type
seems to hint that your tried to send a GET request. It is rather unusual (allthough technically the HTTP protocol allows this) that servers require a GET request with a body. So my best guess is that there is something wrong with the server.
I'm working on a proxy that will relay connections to another server. I had implemented a IHttpHandler that takes requests for a specific address and sends them to my proxy.
My proxy basically starts a sockect connection to the proxied server and reads the original request:
var requestString = new StreamReader(httpRequest.InputStream).ReadToEnd();
My problem arises at this point: the input stream only contains the stream of the body of the HTTP request, not the complete request.
How can I retrieve the full HTTP Request without having to reconstruct it from the HttpRequest object?
I don't know of a definitive one-liner in ASP .NET, but you can get pretty close, as shown in this forum post. What is suggested there is to build the first line out of HttpRequest properties, then add ServerVariables["ALL_RAW"], then the request body in the InputStream as you're already doing.
The only way to get the 'full HTTP Request' object is to actually reconstruct it in some way. I'm not sure you need the whole object for this process though. Perhaps you could just grab a subset of the items in HttpRequest for processing? You could manually concatenate the various portions of the object you need into something new. Once you deviate from using HttpRequest though, it's all custom to me.
I'm trying to send a POST request with parameters and a body (via C# for Windows Phone). In order to send parameters, I need to use application/x-www-form-urlencoded for the Content-Type header.
Only problem is the server I'm communicating with expects me to have Content-Type set to something else (a custom value).
Basically for a link in the form of ip/path/file?param1=value1¶m2=value2, sent via POST with the POST body being JSON content, I need to set Content-Type to something custom, but still have the parameters sent.
Is there any conceivable way of doing this? I realize it's a bit of a paradox. Changing the server API to respond to other Content-Type headers is not possible.
Some headers can be set using API properties only.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.androidlost.com/androidlost/greet");
request.ContentType = "text/x-gwt-rpc; charset=utf-8";
I found the answer shortly after posting the question. It seems that if I construct the URL string to include the actual parameters it works like a charm.
This is oppposed to the situation where I would add parameters problematically via HTTP Requests api.
I'm on IIS 6 and I have an ASP.Net 4.0 site that's a single page to serve as a SOAP reverse proxy. I have to modify the return content in order to delete a trouble node from the response and add a tracking node.
In order to facilitate its function as a reverse proxy for all addresses, I have the 404 on the server set to a custom "URL" of "/default.aspx" (the page for my app)
For requests without a payload, it works perfectly - such as for ?WSDL Urls. It requests the proper URL from the target system, gets the response and sends it back - it's pretty utterly transparent in this regard.
However, when a SOAP request is being made with an input payload, the Request.InputStream in the code is always empty. Empty - with one exception - using SOAPUI, I can override the end point and send the request directly to /default.aspx and it will receive the input payload. Thus, I have determined that the custom 404 handler is - when server-side transferring the request - stripping the payload. I know the payload is being sent - I have even wiresharked it on the server to be sure. But then when I add code to log the contents of Request.InputStream it's blank - even though Request.ContentLength shows the right content length for the original request.
I've also been looking for a good way to use ASP.Net to intercept the requests directly rather than allowing the normal IIS 404 handler to take care of it but even with a wildcard mapping, I can't seem to get the settings right nor am I fully confident that it would help. (But I'm hoping it would?)
Finally, I don't have corporate permission to install MVC framework.
Thus, I need either some configuration for IIS I am missing to make this work properly or some other method of ensuring that I get the request payload to my web page.
Thanks!
What about using an HTTP Handler mapped to all requests?
You'll need to add a wildcard application mapping as detailed here and correctly configure your HTTP Handler.