I want to send an HTTP GET with a request body. I know there is much heated debate about whether this should ever be done or not but I am not interested in debating it I simply want to do it. I'm using C# and ASP.NET and my code is below. Unfortunately it throws an exception "Cannot send a content-body with this verb type". Please, any help on how to get this done will be very appreciated!
// Serialize our concrete class into a JSON String
var stringPayload = JsonConvert.SerializeObject(memRequest);
// Wrap our JSON inside a StringContent which then can be used by the HttpClient class
var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json");
using (var httpClient = new HttpClient())
{
HttpRequestMessage request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = u,
Content = httpContent
};
var result = httpClient.SendAsync(request).Result;
result.EnsureSuccessStatusCode();
var responseBody = result.Content.ReadAsStringAsync().ConfigureAwait(false);
Related
I am working on this helper method that will call an API using the body section. I am passing in the url and data in the model. Then I SerializeObject the model, but I am not sure what to return I get the error message about the response.Content is not found.
public static async System.Threading.Tasks.Task<HttpResponse> HttpClientHandlerAsync(string url, object model)
{
var fullUrl = apiUrl + url;
var json = JsonConvert.SerializeObject(model);
var data = new StringContent(json, Encoding.UTF8, "application/json");
Client.DefaultRequestHeaders.Add("Accept", "*/*");
Client.DefaultRequestHeaders.Authorization
= new AuthenticationHeaderValue("Bearer", "token");
var response = await Client.PostAsync(fullUrl, data);
return response;
}
Add await in front of your
await Client.PostAsync(fullUrl, data);
Because you're trying to get content of Task
I am not sure what to return I get the error message about the response.Content is not found.
Set a breakpoint and hover over the response to see the status code. You could have a 500 server error, authentication error etc.
Furthermore
using (var client = new HttpClient())
Do not do this. It doesn't work the way you think it does, it will starve your connection pool and eventually throw an exception. You need to define the HttpClient somewhere and continue to reuse the same instance.
Further reading if you care https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
I'm a trying to post the following request but I am getting a "Unsupported Media Type" response. I am setting the Content-Type to application/json. Any help would be appreciated. And as per comment below, if i change content as 'new StringContent(JsonConvert.SerializeObject(root), Encoding.UTF8, "application/json")' then i get bad request response
string URL = "https://test.com/api/v2/orders/"; //please note it is dummy api endpoint
var client = new HttpClient();
var httpRequestMessage = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(URL),
Headers = {
{ HttpRequestHeader.Authorization.ToString(), "Bearer ABcdwenlfbl8HY0aGO9Z2NacFj1234" }, //please note it is dummy bearer token
{ HttpRequestHeader.Accept.ToString(), "application/json;indent=2" },
{ HttpRequestHeader.ContentType.ToString(), "application/json" }
},
//Content =new StringContent(JsonConvert.SerializeObject(root), Encoding.UTF8, "application/json")
Content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(root))
};
var response = client.SendAsync(httpRequestMessage).Result;
With HttpClient, some headers are counted as request headers, and others are counted as content headers. I'm not sure why they made this distinction really, but the bottom line is that you have to add headers in the correct place.
In the case of Content-Type, this can be added as part of the StringContent constructor, or to the constructed StringContent object.
My approach is to use the constructor:
Content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(root), System.Text.Encoding.UTF8, "application/json");
Or alternatively set it afterwards:
Content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(root))
Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
Note: If your issue still presents after making this change, then it's likely a server-side problem and you'll need to contact the maintainer of the API to ask what you're doing wrong.
I prefer using some third party wrappers like FluentClient
Note that you should not instance a new object for every request, O only did it for the sake of an example.
var client = new FluentClient("https://test.com/api/v2/orders/")
.PostAsync(URI)
.WithBody(root)
.WithBearerAuthentication("ABcdwenlfbl8HY0aGO9Z2NacFj1234");
var response = await client.AsResponse();
I came with an issue this morning where the Api which I am calling is a Get Method but to get Get the Data from it I had to send the json body this is working good when I am testing it in the post man but I am not able to implement it in my project where I am calling this using HttpClient
here is the screenshot of post
It also have a bearer token which I pass in Authorization
Now when I am try to implement this at client side here is my code
var stringPayload = JsonConvert.SerializeObject(json);
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://myapiendpoint/serviceability/"),
Content = new StringContent(stringPayload, Encoding.UTF8, "application/json"),
};
var response = await client.SendAsync(request).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
when I call this method using this code I get
System.Net.HttpStatusCode.MethodNotAllowed - Status code 405
I also tried changing this line
Method = HttpMethod.Get to Method = HttpMethod.Post
but still getting same error
I know this is bad implementation at API Side the request ideally should be POST but changing this is not in my hand and hence need to find the solution
almost search all over and trying all the variant of using GET Method finally the solution which worked for me in this case was this
var client = new HttpClient();
client.BaseAddress = new Uri("https://baseApi/");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer {0}", token));
var query = new Dictionary<string, string>
{
["pickup_postcode"] = 400703,
["delivery_postcode"] = 421204,
["cod"] = "0",
["weight"] = 2,
};
var url = "methodurl";
var response = await client.GetAsync(QueryHelpers.AddQueryString(url, query));
var responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return JsonConvert.DeserializeObject<MyModel>(responseBody);
Got QueryHelpers from Microsoft.AspNetCore.WebUtilities package
I am trying to send a POST request from my ASP.NET Core Web API Project but the request is never sent. The method gets executed with no errors but the request never gets sent out from the async method.
My Implementation:
public async void notify(String message)
{
String url = "MY_WEBSERVICE_URL";
var client = new HttpClient();
client.BaseAddress = new Uri(url);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "relativeAddress");
request.Content = new StringContent("application/x-www-form-urlencoded;charset=UTF-8",
Encoding.UTF8, "application/json");
Byte[] byteArray = Encoding.UTF8.GetBytes("{\"text\":\"" + message + "\"}");
request.Content.Headers.ContentLength = byteArray.Length;
await client.SendAsync(request).ContinueWith(responseTask =>
{
Console.WriteLine("Response: {0}", responseTask.Result);
});
}
Is this the proper way of making a POST request from a Core Web API project? Thank you in advance
First of all, there is a dedicated method PostAsync in the HttpClient class ( or even PostAsJsonAsync extension) which you can use to send POST requests without creating HttpRequstMessage manually.
Now about your code - I believe you want to post following JSON string:
{"text":"someMessage"}
You should set this string as a content of StringContent which you are sending:
var json = "{\"text\":\"" + message + "\"}";
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
Currently you are trying to post mediatype string as a value to your API endpoint. Of course it cannot be deserialized into your model.
Note1: StringContent will automatically add Content-Length header with the appropriate value. You should not do that manually.
Note2: Unless this is an event handler, you should not use async void - use async Task instead.
Same task with PostAsJsonAsync usage will look like:
public async Task Notify(string message)
{
var string url = "MY_WEBSERVICE_URL";
var client = new HttpClient();
client.BaseAddress = new Uri(url);
var notification = new Notification { Text = message }; // use some model class
var resonse = await client.PostAsJsonAsync("relativeAddress", notification);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
}
}
In this case, your model will be automatically serialized into JSON, appropriate content will be created and POST request will be sent.
Try Adding [IgnoreAntiforgeryToken] on top of the Post Action like this
I'm trying to get a response from a HTTP request but i seem to be unable to. I have tried the following:
public Form1() {
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("someUrl");
string content = "someJsonString";
HttpRequestMessage sendRequest = new HttpRequestMessage(HttpMethod.Post, client.BaseAddress);
sendRequest.Content = new StringContent(content,
Encoding.UTF8,
"application/json");
Send message with:
...
client.SendAsync(sendRequest).ContinueWith(responseTask =>
{
Console.WriteLine("Response: {0}", responseTask.Result);
});
} // end public Form1()
With this code, i get back the status code and some header info, but i do not get back the response itself. I have tried also:
HttpResponseMessage response = await client.SendAsync(sendRequest);
but I'm then told to create a async method like the following to make it work
private async Task<string> send(HttpClient client, HttpRequestMessage msg)
{
HttpResponseMessage response = await client.SendAsync(msg);
string rep = await response.Content.ReadAsStringAsync();
}
Is this the preferred way to send a 'HttpRequest', obtain and print the response? I'm unsure what method is the right one.
here is a way to use HttpClient, and this should read the response of the request, in case the request return status 200, (the request is not BadRequest or NotAuthorized)
string url = 'your url here';
// usually you create on HttpClient per Application (it is the best practice)
HttpClient client = new HttpClient();
using (HttpResponseMessage response = client.GetAsync(url).GetAwaiter().GetResult())
{
using (HttpContent content = response.Content)
{
var json = content.ReadAsStringAsync().GetAwaiter().GetResult();
}
}
and for full details and to see how to use async/await with HttpClient you could read the details of this answer