I have to send a delete command to a REST API service with JSON content using the HttpClient class and can't make this working.
API call:
DELETE /xxx/current
{
"authentication_token": ""
}
because I can't add any content into below statement:
HttpResponseMessage response = client.DeleteAsync(requestUri).Result;
I know how to make this work with RestSharp:
var request = new RestRequest {
Resource = "/xxx/current",
Method = Method.DELETE,
RequestFormat = DataFormat.Json
};
var jsonPayload = JsonConvert.SerializeObject(cancelDto, Formatting.Indented);
request.Parameters.Clear();
request.AddHeader("Content-type", "application/json");
request.AddHeader ("Accept", "application/json");
request.AddParameter ("application/json", jsonPayload, ParameterType.RequestBody);
var response = await client.ExecuteTaskAsync (request);
but I have get it done without RestSharp.
Although it might be late to answer this question but
I've faced a similar problem and the following code worked for me.
HttpRequestMessage request = new HttpRequestMessage
{
Content = new StringContent("[YOUR JSON GOES HERE]", Encoding.UTF8, "application/json"),
Method = HttpMethod.Delete,
RequestUri = new Uri("[YOUR URL GOES HERE]")
};
await httpClient.SendAsync(request);
UPDATE on .NET 5
.NET 5 introduced JsonContent. Here is an extension method using JsonContent:
public static async Task<HttpResponseMessage> DeleteAsJsonAsync<TValue>(this HttpClient httpClient, string requestUri, TValue value)
{
HttpRequestMessage request = new HttpRequestMessage
{
Content = JsonContent.Create(value),
Method = HttpMethod.Delete,
RequestUri = new Uri(requestUri, UriKind.Relative)
};
return await httpClient.SendAsync(request);
}
You can use these extension methods:
public static class HttpClientExtensions
{
public static Task<HttpResponseMessage> DeleteAsJsonAsync<T>(this HttpClient httpClient, string requestUri, T data)
=> httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Delete, requestUri) { Content = Serialize(data) });
public static Task<HttpResponseMessage> DeleteAsJsonAsync<T>(this HttpClient httpClient, string requestUri, T data, CancellationToken cancellationToken)
=> httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Delete, requestUri) { Content = Serialize(data) }, cancellationToken);
public static Task<HttpResponseMessage> DeleteAsJsonAsync<T>(this HttpClient httpClient, Uri requestUri, T data)
=> httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Delete, requestUri) { Content = Serialize(data) });
public static Task<HttpResponseMessage> DeleteAsJsonAsync<T>(this HttpClient httpClient, Uri requestUri, T data, CancellationToken cancellationToken)
=> httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Delete, requestUri) { Content = Serialize(data) }, cancellationToken);
private static HttpContent Serialize(object data) => new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
}
The answer from Farzan Hajian still didn't work for me, I could set the request content but it wasn't actually sent to the server.
As an alternative you could look at using the X-HTTP-Method-Override header. This tells the server that you want it to treat the request as if you sent a different verb than the one that you actually sent. You will have to ensure that the server handles this header correctly, but if it does you can just POST the request and add: X-HTTP-Method-Override:DELETE to the headers and it will be the equivalent of a DELETE request with a body.
Try with
Edited
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.your.url");
request.Method = "DELETE";
request.ContentType = "application/json";
request.Accept = "application/json";
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
string json = "{\"key\":\"value\"}";
streamWriter.Write(json);
streamWriter.Flush();
}
using (var httpResponse = (HttpWebResponse)request.GetResponse())
{
// do something with response
}
Here you can find very similar problem.
Edited
I am not sure that passing request body for DELETE request is good approach. Especially when this is only for your authentication purposes. I will prefer to put authentication_token to Headers. It is because in my solution I will not have to parse the whole request body to check that current request is correctly authenticated. What about other request types? Do you always pass authentication_token in request body?
Related
I'm sending a request in JSON format to an API, but the response comes back (content variable) in XML format (Content-type=XML) instead of JSON.
Why it's happening and how can I fix that?
public async Task<TransactionResponse> Capture(GatewayTransaction request)
{
var captureTransaction = PayURequestMapper.GetCapturePayload(request, this.gateway);
HttpContent httpContent = new StringContent(captureTransaction, Encoding.UTF8, "application/json");
var response = await this.restClient.PostAsync(
this.gateway?.TargetURL,
httpContent, true);
var content = response.Content.ReadAsStringAsync().Result;
return transactionResponse;
}
I'm sending JSON request with PostAsync:
public async Task<HttpResponseMessage> PostAsync(string url, HttpContent content, bool acceptHeader = false, string headerType = null)
{
HttpResponseMessage responseMessage;
if (acceptHeader)
{
this.httpClient.DefaultRequestHeaders.Add("Accept", headerType);
}
using (content)
{
responseMessage = await this.httpClient.PostAsync(url, content);
}
return responseMessage;
}
As #Javad mentioned in the comments, adding content-type with value application/json solved the problem. In my case, I had to pass "application/json" to PostAsync as a parameter
In my requests to Spotify's "get token" endpoint using .NET's HttpRequestMessage, I'm getting a 406 (Unacceptable) response.
Here's my post method (fyi, this is not optimized code -- more of a proof of concept):
public static async Task<string> PostForm(HttpClient httpClient, string url, List<KeyValuePair<string, string>> nameValueList)
{
using (var httpRequest = new HttpRequestMessage(HttpMethod.Post, url))
{
httpRequest.Content = new FormUrlEncodedContent(nameValueList);
using (var response = await httpClient.SendAsync(httpRequest))
{
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
}
I'm calling that method with this:
public Token GetSpotifyToken()
{
var httpClient= new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
httpClient.DefaultRequestHeaders.Add("Authorization", "Basic MyApiCredsBase64EncodedYesIveConfirmedTheseWork=");
var url = "https://accounts.spotify.com/api/token";
var grantType = new KeyValuePair<string, string>("grant_type", "client_credentials");
return JsonConvert.DeserializeObject<Token>
(ApiRequest.PostForm(postClient, url,
new List<KeyValuePair<string, string>>() { grantType } )
.GetAwaiter()
.GetResult());
}
I know that the issue is related to how grant_type=client_credentials is getting added to the request. This method, which uses RestSharp, works fine:
public Token GetSpotifyToken()
{
var client = new RestClient("https://accounts.spotify.com/api/token");
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("Authorization", "Basic MyApiCredentialsBase64Encoded=");
request.AddParameter("undefined", "grant_type=client_credentials", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
return JsonConvert.DeserializeObject<Token>(response.Content);
}
But I've tried adding grant_type=client_credentials to the HttpRequestMessage object in a few different ways, without success.
Figured it out, right after I posted this.
In the above code, the line...
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
...was causing the problem. Omitting it allowed the code to work.
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
Any way to retrieve the POST Request Body of Http Client in C#? I just want to check in my UT if my extension method is adding it properly to the request or not. This function is not doing any justice to it.
public static async Task<string> AddPostRequestBody<T>(this HttpClient httpclient, string RequestUrl, T classobject)
{
string json_body = Newtonsoft.Json.JsonConvert.SerializeObject(classobject);
HttpRequestMessage RequestMessage = new HttpRequestMessage(HttpMethod.Post, RequestUrl);
HttpResponseMessage response = await httpclient.PostAsync(RequestUrl, new StringContent(json_body));
response = httpclient.SendAsync(RequestMessage).Result;
string outputresult = await response.RequestMessage.Content.ReadAsStringAsync();
return outputresult;
}
Please help !
Try using a DelegatingHandler (which I've used in implementing HMAC to hash the content and add the necessary authorization headers), this will let you access the content.
CustomDelegatingHandler customDelegatingHandler = new CustomDelegatingHandler();
HttpClient client = HttpClientFactory.Create(customDelegatingHandler);
public class CustomDelegatingHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.Content != null)
{
byte[] content = await request.Content.ReadAsByteArrayAsync();
// Do what you need with the content here
}
response = await base.SendAsync(request, cancellationToken);
return response;
}
}
Okay so I got it working with this instead of creating a response, I am directly appending to the request message and retrieving from it. Simple one but initially in the posted question, I made it complicated by adding the json string to response.
public static string AddPostRequestBody<T>(this HttpClient httpclient, string requestUrl, T classObject)
{
string jsonBody = Newtonsoft.Json.JsonConvert.SerializeObject(classObject);
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, requestUrl);
requestMessage.Content = new StringContent(jsonBody);
string requestBody = requestMessage.Content.ReadAsStringAsync().Result;
return requestBody;
}