I am using RestSharp for developing on the client side. I am also using Ruby Grape gem for my custom API on server side. Grape gem can do versioning by setting Accept HTTP header f.e to application/vnd.twitter-v1+json
And test command via console works perfect
curl -H Accept=application/vnd.twitter-v1+json /statuses/public_timeline
But when I am trying to set up header for RestRequest I am getting error 404 on the server.
I have no idea why so. I have found another issue that server returns 406 error - but in my case 404.
How can I put custom value for Accept header?
You can set a custom Accept header with the AddHeader method...
var client = new RestClient("http://example.com/api");
var request = new RestRequest("statuses/public_timeline", Method.GET);
request.AddHeader("Accept", "application/vnd.twitter-v1+json");
var response = client.Execute(request);
var json = response.Content;
This should work fine if you are willing to deserialize the JSON yourself.
If you want to make use of the generic Execute<T> method, which does automatic deserialization for you, you will run into problems...
From the RestSharp documentation about deserialization:
RestSharp includes deserializers to process XML and JSON. Upon receiving a response, RestClient chooses the correct deserializer to use based on the Content Type returned by the server. The defaults can be overridden (see Customization). The built-in content types supported are:
application/json – JsonDeserializer
application/xml – XmlDeserializer
text/json – JsonDeserializer
text/xml – XmlDeserializer
* – XmlDeserializer (all other content types not specified)
This is saying that, by default, if the response's content type is not one of those listed, RestSharp will attempt to use the XmlDeserializer on your data. This is customizable though with extra work.
Related
I want to send information about the current client version from the server in all responses to the callers.
I want to have this information in the HTTP header. But I am not able to read the headers in the client.
I call the method WriteResponseHeaderAsync in the server method or interceptor (tried both). I see (Fiddler) that the header is in the response header.
But, I cannot read this header on the client or in the interceptor on the client. I tried everything.
My code in method:
var result = AuthorizationClient.LoginAsync(loginRequest);
var responseHeaders = await result.ResponseHeadersAsync;
ResponseHeaders is empty (responseHeaders.Count is 0) all time. I am able to use Trailers but the right place is HTTP header.
Is possible to read the response headers? Is possible to read the response headers in interceptors?
If yes, how?
I am using: C#, Grpc.AspNetCore.Web 2.51.0 (on server), Grpc.Net.Client.Web 2.51.0 (Client. Blazor WebAssembly)
I want to call an endpoint with a Put command.
In Postman
I can put example https://example.com/customers/106. I then add a body of type application/json (under raw).
When I Put this body to the endpoint, I get a 200 OK.
The endpoint I use requires two custom headers and a content-type, which I have made under headers. So I add three headers: X-AppSecretToken, X-AgreementGrantToken and the Content-Type (to application/json).
In RestSharp
Here I use the following. The putstr is the exact same body I Put as I do in Postman:
var restclient = new RestSharp.RestClient("https://example.com");
var request = new RestRequest("/customers/" + customerId, Method.PUT);
request.AddHeader("X-AppSecretToken", systemToken);
request.AddHeader("X-AgreementGrantToken", userToken);
request.AddHeader("Accept", "application/json");
request.AddJsonBody(putstr);
var response = restclient.Execute(request);
Now, when I do this, I get the following response which is a custom error from the API I am calling:
"{\"message\":\"Error converting value SOME STUFF}}\\\" to type 'eco.rest.Models.Customer'. Path '', line 1, position 605.\",\"errorCode\":\"E00500\",\"developerHint\":\"The JSON payload could not be parsed. The error message should give you a good indication of where the error is located. One common reason for this error is a missing '{' or a '}' in your payload.\",\"logId\":\"123fc6fb4964a141f612ae8ae7571446\",\"httpStatusCode\":400,\"logTime\":\"2018-05-20T21:56:56\"}"
How to fix?
Normally, I'd never ask this question. If someone else asked, I would say: open Fiddler or a similar tool and see how requests are different.
I have some troubles with this, because it's HTTPS.
When I debug through my code, I simply don't see the call inside Fiddler. I also installed Charles, but also no luck. Not sure what the problem is.
However, I thought that someone who reads this can probably come up with the problem. My own assumptions are I maybe have added the headers in a wrong way, the JSON body is encoded different or similar - but I am really unsure how to move on. I hope someone can help!
Your putstr value seems to be a JSON value.
AddJsonBody will convert this JSON value into another JSON value.
You should use the original object instead of putstr.
I have the following code in .Net Core:
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Bearer " + _accessToken);
client.DefaultRequestHeaders.TryAddWithoutValidation("Dropbox-API-Arg", GenerateJsonFromObject(new {path = filePath}));
var request = new HttpRequestMessage(HttpMethod.Post, "https://content.dropboxapi.com/2/files/download");
var result = client.SendAsync(request).Result;
}
As you can see it's quite simple piece of code and it works correctly, but only on Windows.
When I'm running the same code on my Linux VPS (Ubuntu 16.04 server with .Net Core 1.0.4) I'm receiving the following error message from Dropbox API:
Error in call to API function "files/download": You provided a non-empty HTTP "Content-Type" header ("application/x-www-form-urlencoded"). This API function requires that the header be missing or empty.
So API requires empty or null Content-Type Header, but somehow in .Net Core this header is automatically added to my request.
The result of printing request headers is the same on Windows and on Linux:
Method: POST, RequestUri: 'https://content.dropboxapi.com/2/files/download', Version: 1.1, Content: <null>, Headers:
{
Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Dropbox-API-Arg: {"path":"/tracklogs/night_ride.gpx"}
}
So my question is:
How to avoid adding Content-Type header automatically by .Net Core?
What I've tried:
1 Set an empty Content-Type header:
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "");
Won't work, even if I set value of header to "application/json" it's automatically changed to application/x-www-form-urlencoded :(
2 Remove whole header:
request.Headers.Remove("Content-Type");
or:
client.DefaultRequestHeaders.Remove("Content-Type");
In both cases I'm receiving the following exception:
Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.'
You are doing a POST. This adds a default content-type for the normally required body.
It's not clear if the specification mandates a body but this the point of a POST over a GET, and is sometimes implemented as required (although of course it might be a blank). In view of this, I suspect .net always adds a content-type header to give that body meaning. https://www.rfc-editor.org/rfc/rfc9110.html#name-method-definitions
Possibly this request should be a GET which doesn't require a body. There may also be alternative ways to make the request which give more control over the construction of the request.
I have the code below in c#, which uses RestClient. The issue is that the headers should not be case-sensitive but looks like they are.
var client = new RestClient(sMA_URL);
var request = new RestRequest(Method.GET);
request.AddHeader("cache-control", "no-cache");
//Without the line below the RestRequest adds some default header which is not acceptable by our server.
request.AddHeader("**Accept**", "*/*");
request.AddHeader("content-type", "application/json");
request.AddHeader("authorization", "Bearer "+sBearerToken);
// Make sure you deserialize this response, for further use. The best way to do this is to create a class and then fill that with the values obtained by the response but if a response is not used many times,
// you can do it the way it has been done in Bearer Token Generation
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
Console.ReadKey();
When I give accept (in lower case) it complains about the content-type but Accept (upper case) works fine.No, error regarding the content-type. I can't figure out if the issue is with the service it's trying to call or with RestClient itself.
This is the status code I get (No exception)
'NotAcceptable Content-Type'
Well the answer is included in the response, its self explanatory.
"NotAcceptable Content-Type"
The message above means that the api, service or endpoint your are trying sending your request to, rejects your request based on the content-type header which is 'application/json'.
Since you are sending a GET request, i don't see why do you need to specify content-type at all.
Try removing the content-type header and probably your request will work.
Adding the content-type header would be used for POST or PUT requests, where you are sending a body/payload in the request (example: json,form data,xml,multipart,etc...), and even for this type of requests it is still not mandatory unless the server you are sending your requests to requires you to specify the content-type.
I'm building a RESTful API client using C# .NET 3.5.
I first started building it with the good old HttpWebClient (and HttpWebResponse), I could do whatever I wanted with. I were happy. The only thing I stumbled upon was the automatic deserialization from JSON response.
So, I've heard about a wonderful library called RestSharp (104.1) which eases the development of RESTful API clients, and automatically deserialize JSON and XML responses. I switched all my code on it, but now I realize I can't do things I could do with HttpWebClient and HttpWebResponse, like access and edit the raw request body.
Anyone has a solution?
Edit: I know how to set the request body (with request.AddBody()), my problem is that I want to get this request body string, edit it, and re-set it in the request (in other words: updating the request body on the fly)
The request body is a type of parameter. To add one, you can do one of these...
req.AddBody(body);
req.AddBody(body, xmlNamespace);
req.AddParameter("text/xml", body, ParameterType.RequestBody);
req.AddParameter("application/json", body, ParameterType.RequestBody);
To retrieve the body parameter you can look for items in the req.Parameters collection where the Type is equal to ParameterType.RequestBody.
See code for the RestRequest class here.
Here is what the RestSharp docs on ParameterType.RequestBody has to say:
If this parameter is set, it’s value will be sent as the body of the
request. The name of the Parameter is ignored, and so are additional
RequestBody Parameters – only 1 is accepted.
RequestBody only works on POST or PUT Requests, as only they actually
send a body.
If you have GetOrPost parameters as well, they will overwrite the
RequestBody – RestSharp will not combine them but it will instead
throw the RequestBody parameter away.
For reading/updating the body parameter on-the-fly, you can try:
var body = req.Parameters.FirstOrDefault(p => p.Type == ParameterType.RequestBody);
if (body != null)
{
Console.WriteLine("CurrentBody={0}", body.Value);
body.Value = "NewBodyValue";
}
Or failing that, create a new copy of the RestRequest object with a different body.